Back to home page

OSCL-LXR

 
 

    


0001 /*! RowsGroup for DataTables v1.0.0
0002  * 2015 Alexey Shildyakov ashl1future@gmail.com
0003  */
0004 
0005 /**
0006  * @summary     RowsGroup
0007  * @description Group rows by specified columns
0008  * @version     1.0.0
0009  * @file        dataTables.rowsGroup.js
0010  * @author      Alexey Shildyakov (ashl1future@gmail.com)
0011  * @contact     ashl1future@gmail.com
0012  * @copyright   Alexey Shildyakov
0013  * 
0014  * License      MIT - http://datatables.net/license/mit
0015  *
0016  * This feature plug-in for DataTables automatically merges columns cells
0017  * based on it's values equality. It supports multi-column row grouping
0018  * in according to the requested order with dependency from each previous 
0019  * requested columns. Now it supports ordering and searching. 
0020  * Please see the example.html for details.
0021  * 
0022  * Rows grouping in DataTables can be enabled by using any one of the following
0023  * options:
0024  *
0025  * * Setting the `rowsGroup` parameter in the DataTables initialisation
0026  *   to array which contains columns selectors
0027  *   (https://datatables.net/reference/type/column-selector) used for grouping. i.e.
0028  *    rowsGroup = [1, 'columnName:name', ]
0029  * * Setting the `rowsGroup` parameter in the DataTables defaults
0030  *   (thus causing all tables to have this feature) - i.e.
0031  *   `$.fn.dataTable.defaults.RowsGroup = [0]`.
0032  * * Creating a new instance: `new $.fn.dataTable.RowsGroup( table, columnsForGrouping );`
0033  *   where `table` is a DataTable's API instance and `columnsForGrouping` is the array
0034  *   described above.
0035  *
0036  * For more detailed information please see:
0037  *     
0038  */
0039 
0040 (function($){
0041 
0042 ShowedDataSelectorModifier = {
0043         order: 'current',
0044         page: 'current',
0045         search: 'applied',
0046 }
0047 
0048 GroupedColumnsOrderDir = 'desc'; // change
0049 
0050 
0051 /*
0052  * columnsForGrouping: array of DTAPI:cell-selector for columns for which rows grouping is applied
0053  */
0054 var RowsGroup = function ( dt, columnsForGrouping )
0055 {
0056         this.table = dt.table();
0057         this.columnsForGrouping = columnsForGrouping;
0058          // set to True when new reorder is applied by RowsGroup to prevent order() looping
0059         this.orderOverrideNow = false;
0060         this.order = []
0061         
0062         self = this;
0063         $(document).on('order.dt', function ( e, settings) {
0064                 if (!self.orderOverrideNow) {
0065                         self._updateOrderAndDraw()
0066                 }
0067                 self.orderOverrideNow = false;
0068         })
0069         
0070         $(document).on('draw.dt', function ( e, settings) {
0071                 self._mergeCells()
0072         })
0073 
0074         this._updateOrderAndDraw();
0075 };
0076 
0077 
0078 RowsGroup.prototype = {
0079         _getOrderWithGroupColumns: function (order, groupedColumnsOrderDir)
0080         {
0081                 if (groupedColumnsOrderDir === undefined)
0082                         groupedColumnsOrderDir = GroupedColumnsOrderDir
0083                         
0084                 var self = this;
0085                 var groupedColumnsIndexes = this.columnsForGrouping.map(function(columnSelector){
0086                         return self.table.column(columnSelector).index()
0087                 })
0088                 var groupedColumnsKnownOrder = order.filter(function(columnOrder){
0089                         return groupedColumnsIndexes.indexOf(columnOrder[0]) >= 0
0090                 })
0091                 var nongroupedColumnsOrder = order.filter(function(columnOrder){
0092                         return groupedColumnsIndexes.indexOf(columnOrder[0]) < 0
0093                 })
0094                 var groupedColumnsKnownOrderIndexes = groupedColumnsKnownOrder.map(function(columnOrder){
0095                         return columnOrder[0]
0096                 })
0097                 var groupedColumnsOrder = groupedColumnsIndexes.map(function(iColumn){
0098                         var iInOrderIndexes = groupedColumnsKnownOrderIndexes.indexOf(iColumn)
0099                         if (iInOrderIndexes >= 0)
0100                                 return [iColumn, groupedColumnsKnownOrder[iInOrderIndexes][1]]
0101                         else
0102                                 return [iColumn, groupedColumnsOrderDir]
0103                 })
0104                 
0105                 groupedColumnsOrder.push.apply(groupedColumnsOrder, nongroupedColumnsOrder)
0106                 return groupedColumnsOrder;
0107         },
0108  
0109         // Workaround: the DT reset ordering to 'desc' from multi-ordering if user order on one column (without shift)
0110         // but because we always has multi-ordering due to grouped rows this happens every time
0111         _getInjectedMonoSelectWorkaround: function(order)
0112         {
0113                 if (order.length === 1) {
0114                         // got mono order - workaround here
0115                         var orderingColumn = order[0][0]
0116                         var previousOrder = this.order.map(function(val){
0117                                 return val[0]
0118                         })
0119                         var iColumn = previousOrder.indexOf(orderingColumn);
0120                         if (iColumn >= 0) {
0121                                 // assume change the direction, because we already has that in previous order
0122                                 return [[orderingColumn, this._toogleDirection(this.order[iColumn][1])]]
0123                         } // else This is the new ordering column. Proceed as is.
0124                 } // else got multi order - work normal
0125                 return order;
0126         },
0127         
0128         _mergeCells: function()
0129         {
0130                 var columnsIndexes = this.table.columns(this.columnsForGrouping, ShowedDataSelectorModifier).indexes().toArray()
0131                 var showedRowsCount = this.table.rows(ShowedDataSelectorModifier)[0].length 
0132                 this._mergeColumn(0, showedRowsCount - 1, columnsIndexes)
0133         },
0134         
0135         // the index is relative to the showed data
0136         //    (selector-modifier = {order: 'current', page: 'current', search: 'applied'}) index
0137         _mergeColumn: function(iStartRow, iFinishRow, columnsIndexes)
0138         {
0139                 var columnsIndexesCopy = columnsIndexes.slice()
0140                 currentColumn = columnsIndexesCopy.shift()
0141                 currentColumn = this.table.column(currentColumn, ShowedDataSelectorModifier)
0142                 
0143                 var columnNodes = currentColumn.nodes()
0144                 var columnValues = currentColumn.data()
0145                 
0146                 var newSequenceRow = iStartRow,
0147                         iRow;
0148                 for (iRow = iStartRow + 1; iRow <= iFinishRow; ++iRow) {
0149                         
0150                         if (columnValues[iRow] === columnValues[newSequenceRow]) {
0151                                 $(columnNodes[iRow]).hide()
0152                         } else {
0153                                 $(columnNodes[newSequenceRow]).show()
0154                                 $(columnNodes[newSequenceRow]).attr('rowspan', (iRow-1) - newSequenceRow + 1)
0155                                 
0156                                 if (columnsIndexesCopy.length > 0)
0157                                         this._mergeColumn(newSequenceRow, (iRow-1), columnsIndexesCopy)
0158                                 
0159                                 newSequenceRow = iRow;
0160                         }
0161                         
0162                 }
0163                 $(columnNodes[newSequenceRow]).show()
0164                 $(columnNodes[newSequenceRow]).attr('rowspan', (iRow-1)- newSequenceRow + 1)
0165                 if (columnsIndexesCopy.length > 0)
0166                         this._mergeColumn(newSequenceRow, (iRow-1), columnsIndexesCopy)
0167         },
0168         
0169         _toogleDirection: function(dir)
0170         {
0171                 return dir == 'asc'? 'desc': 'asc';
0172         },
0173  
0174         _updateOrderAndDraw: function()
0175         {
0176                 this.orderOverrideNow = true;
0177                 
0178                 var currentOrder = this.table.order();
0179                 currentOrder = this._getInjectedMonoSelectWorkaround(currentOrder);
0180                 this.order = this._getOrderWithGroupColumns(currentOrder)
0181                 // this.table.order($.extend(true, Array(), this.order)) // disable this line in order to support sorting on non-grouped columns
0182                 this.table.draw(false)
0183         },
0184 };
0185 
0186 
0187 $.fn.dataTable.RowsGroup = RowsGroup;
0188 $.fn.DataTable.RowsGroup = RowsGroup;
0189 
0190 // Automatic initialisation listener
0191 $(document).on( 'init.dt', function ( e, settings ) {
0192         if ( e.namespace !== 'dt' ) {
0193                 return;
0194         }
0195 
0196         var api = new $.fn.dataTable.Api( settings );
0197 
0198         if ( settings.oInit.rowsGroup ||
0199                  $.fn.dataTable.defaults.rowsGroup )
0200         {
0201                 options = settings.oInit.rowsGroup?
0202                         settings.oInit.rowsGroup:
0203                         $.fn.dataTable.defaults.rowsGroup;
0204                 new RowsGroup( api, options );
0205         }
0206 } );
0207 
0208 }(jQuery));
0209 
0210 /*
0211 
0212 TODO: Provide function which determines the all <tr>s and <td>s with "rowspan" html-attribute is parent (groupped) for the specified <tr> or <td>. To use in selections, editing or hover styles.
0213 
0214 TODO: Feature
0215 Use saved order direction for grouped columns
0216         Split the columns into grouped and ungrouped.
0217 
0218         user = grouped+ungrouped
0219         grouped = grouped
0220         saved = grouped+ungrouped
0221 
0222         For grouped uses following order: user -> saved (because 'saved' include 'grouped' after first initialisation). This should be done with saving order like for 'groupedColumns'
0223         For ungrouped: uses only 'user' input ordering
0224 */