jquery-datatables-rails 2.2.3 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js +59 -6
- data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +747 -596
- data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnSetFilteringDelay.js +2 -2
- data/app/assets/javascripts/dataTables/jquery.dataTables.js +2119 -1969
- data/app/assets/stylesheets/dataTables/extras/dataTables.responsive.css.scss +128 -85
- data/app/assets/stylesheets/dataTables/jquery.dataTables.css +476 -0
- data/app/assets/stylesheets/dataTables/jquery.dataTables.css.scss +5 -5
- data/lib/jquery/datatables/rails/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ca11d8aeb50210204b7e77bb8e1e97f896c2cb1
|
4
|
+
data.tar.gz: ca675097df780258be6de80ebbce4e638893a6bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 272b904d03a7ccbf8bb94af7addd12a7c6e01e8012d17c6ba027e696c914496228f7a9d6286dec386e61146732e963206e314aedbf487846676ab4b61e81fedb
|
7
|
+
data.tar.gz: 9e64a787991fdd21f07b327cff8da3a972803d6d83c8a7ea4a9179c39a452860ca2fb879573ffa5307b0877b03091cf7590e7c1e913b8148f8cca942b0be973f
|
@@ -1,8 +1,19 @@
|
|
1
|
+
/* Set the defaults for DataTables initialisation */
|
2
|
+
$.extend( true, $.fn.dataTable.defaults, {
|
3
|
+
"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
|
4
|
+
"sPaginationType": "bootstrap",
|
5
|
+
"oLanguage": {
|
6
|
+
"sLengthMenu": "_MENU_ records per page"
|
7
|
+
}
|
8
|
+
} );
|
9
|
+
|
10
|
+
|
1
11
|
/* Default class modification */
|
2
12
|
$.extend( $.fn.dataTableExt.oStdClasses, {
|
3
13
|
"sWrapper": "dataTables_wrapper form-inline"
|
4
14
|
} );
|
5
15
|
|
16
|
+
|
6
17
|
/* API method to get paging information */
|
7
18
|
$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
|
8
19
|
{
|
@@ -12,10 +23,13 @@ $.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
|
|
12
23
|
"iLength": oSettings._iDisplayLength,
|
13
24
|
"iTotal": oSettings.fnRecordsTotal(),
|
14
25
|
"iFilteredTotal": oSettings.fnRecordsDisplay(),
|
15
|
-
"iPage":
|
16
|
-
|
26
|
+
"iPage": oSettings._iDisplayLength === -1 ?
|
27
|
+
0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
|
28
|
+
"iTotalPages": oSettings._iDisplayLength === -1 ?
|
29
|
+
0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
|
17
30
|
};
|
18
|
-
}
|
31
|
+
};
|
32
|
+
|
19
33
|
|
20
34
|
/* Bootstrap style pagination control */
|
21
35
|
$.extend( $.fn.dataTableExt.oPagination, {
|
@@ -41,10 +55,10 @@ $.extend( $.fn.dataTableExt.oPagination, {
|
|
41
55
|
},
|
42
56
|
|
43
57
|
"fnUpdate": function ( oSettings, fnDraw ) {
|
44
|
-
var iListLength =
|
58
|
+
var iListLength = 5;
|
45
59
|
var oPaging = oSettings.oInstance.fnPagingInfo();
|
46
60
|
var an = oSettings.aanFeatures.p;
|
47
|
-
var i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
|
61
|
+
var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
|
48
62
|
|
49
63
|
if ( oPaging.iTotalPages < iListLength) {
|
50
64
|
iStart = 1;
|
@@ -61,7 +75,7 @@ $.extend( $.fn.dataTableExt.oPagination, {
|
|
61
75
|
iEnd = iStart + iListLength - 1;
|
62
76
|
}
|
63
77
|
|
64
|
-
for ( i=0,
|
78
|
+
for ( i=0, ien=an.length ; i<ien ; i++ ) {
|
65
79
|
// Remove the middle elements
|
66
80
|
$('li:gt(0)', an[i]).filter(':not(:last)').remove();
|
67
81
|
|
@@ -93,3 +107,42 @@ $.extend( $.fn.dataTableExt.oPagination, {
|
|
93
107
|
}
|
94
108
|
}
|
95
109
|
} );
|
110
|
+
|
111
|
+
|
112
|
+
/*
|
113
|
+
* TableTools Bootstrap compatibility
|
114
|
+
* Required TableTools 2.1+
|
115
|
+
*/
|
116
|
+
if ( $.fn.DataTable.TableTools ) {
|
117
|
+
// Set the classes that TableTools uses to something suitable for Bootstrap
|
118
|
+
$.extend( true, $.fn.DataTable.TableTools.classes, {
|
119
|
+
"container": "DTTT btn-group",
|
120
|
+
"buttons": {
|
121
|
+
"normal": "btn",
|
122
|
+
"disabled": "disabled"
|
123
|
+
},
|
124
|
+
"collection": {
|
125
|
+
"container": "DTTT_dropdown dropdown-menu",
|
126
|
+
"buttons": {
|
127
|
+
"normal": "",
|
128
|
+
"disabled": "disabled"
|
129
|
+
}
|
130
|
+
},
|
131
|
+
"print": {
|
132
|
+
"info": "DTTT_print_info modal"
|
133
|
+
},
|
134
|
+
"select": {
|
135
|
+
"row": "active"
|
136
|
+
}
|
137
|
+
} );
|
138
|
+
|
139
|
+
// Have the collection use a bootstrap compatible dropdown
|
140
|
+
$.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
|
141
|
+
"collection": {
|
142
|
+
"container": "ul",
|
143
|
+
"button": "li",
|
144
|
+
"liner": "a"
|
145
|
+
}
|
146
|
+
} );
|
147
|
+
}
|
148
|
+
|
@@ -1,650 +1,801 @@
|
|
1
|
+
/*! Responsive 1.0.2
|
2
|
+
* 2014 SpryMedia Ltd - datatables.net/license
|
3
|
+
*/
|
4
|
+
|
1
5
|
/**
|
2
|
-
*
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
6
|
+
* @summary Responsive
|
7
|
+
* @description Responsive tables plug-in for DataTables
|
8
|
+
* @version 1.0.2
|
9
|
+
* @file dataTables.responsive.js
|
10
|
+
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
11
|
+
* @contact www.sprymedia.co.uk/contact
|
12
|
+
* @copyright Copyright 2014 SpryMedia Ltd.
|
6
13
|
*
|
7
|
-
*
|
8
|
-
*
|
9
|
-
* This source file is free software, under either the GPL v2 license or a
|
10
|
-
* BSD style license.
|
14
|
+
* This source file is free software, available under the following license:
|
15
|
+
* MIT license - http://datatables.net/license/mit
|
11
16
|
*
|
12
17
|
* This source file is distributed in the hope that it will be useful, but
|
13
18
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
14
19
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
15
20
|
*
|
16
|
-
*
|
17
|
-
* BSD license along with this program. These licenses are also available at:
|
18
|
-
* https://raw.github.com/Comanche/datatables-responsive/master/license-gpl2.txt
|
19
|
-
* https://raw.github.com/Comanche/datatables-responsive/master/license-bsd.txt
|
21
|
+
* For details please refer to: http://www.datatables.net
|
20
22
|
*/
|
21
23
|
|
22
|
-
|
24
|
+
(function(window, document, undefined) {
|
25
|
+
|
26
|
+
|
27
|
+
var factory = function( $, DataTable ) {
|
28
|
+
"use strict";
|
23
29
|
|
24
30
|
/**
|
25
|
-
*
|
31
|
+
* Responsive is a plug-in for the DataTables library that makes use of
|
32
|
+
* DataTables' ability to change the visibility of columns, changing the
|
33
|
+
* visibility of columns so the displayed columns fit into the table container.
|
34
|
+
* The end result is that complex tables will be dynamically adjusted to fit
|
35
|
+
* into the viewport, be it on a desktop, tablet or mobile browser.
|
26
36
|
*
|
27
|
-
*
|
37
|
+
* Responsive for DataTables has two modes of operation, which can used
|
38
|
+
* individually or combined:
|
28
39
|
*
|
29
|
-
*
|
30
|
-
*
|
40
|
+
* * Class name based control - columns assigned class names that match the
|
41
|
+
* breakpoint logic can be shown / hidden as required for each breakpoint.
|
42
|
+
* * Automatic control - columns are automatically hidden when there is no
|
43
|
+
* room left to display them. Columns removed from the right.
|
31
44
|
*
|
32
|
-
*
|
45
|
+
* In additional to column visibility control, Responsive also has built into
|
46
|
+
* options to use DataTables' child row display to show / hide the information
|
47
|
+
* from the table that has been hidden. There are also two modes of operation
|
48
|
+
* for this child row display:
|
33
49
|
*
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
37
|
-
* }
|
50
|
+
* * Inline - when the control element that the user can use to show / hide
|
51
|
+
* child rows is displayed inside the first column of the table.
|
52
|
+
* * Column - where a whole column is dedicated to be the show / hide control.
|
38
53
|
*
|
39
|
-
*
|
40
|
-
* attribute. The data-hide attribute is optional and may be defined for each
|
41
|
-
* th element in the table header.
|
54
|
+
* Initialisation of Responsive is performed by:
|
42
55
|
*
|
43
|
-
*
|
44
|
-
*
|
56
|
+
* * Adding the class `responsive` or `dt-responsive` to the table. In this case
|
57
|
+
* Responsive will automatically be initialised with the default configuration
|
58
|
+
* options when the DataTable is created.
|
59
|
+
* * Using the `responsive` option in the DataTables configuration options. This
|
60
|
+
* can also be used to specify the configuration options, or simply set to
|
61
|
+
* `true` to use the defaults.
|
45
62
|
*
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
49
|
-
*
|
50
|
-
*
|
51
|
-
* }
|
63
|
+
* @class
|
64
|
+
* @param {object} settings DataTables settings object for the host table
|
65
|
+
* @param {object} [opts] Configuration options
|
66
|
+
* @requires jQuery 1.7+
|
67
|
+
* @requires DataTables 1.10.1+
|
52
68
|
*
|
53
|
-
*
|
54
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
*
|
69
|
+
* @example
|
70
|
+
* $('#example').DataTable( {
|
71
|
+
* responsive: true
|
72
|
+
* } );
|
73
|
+
* } );
|
58
74
|
*/
|
59
|
-
function
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
this.cookieName = 'DataTablesResponsiveHelper_' + this.tableId + (fileName ? '_' + fileName : '');
|
84
|
-
this.lastStateExists = false;
|
85
|
-
|
86
|
-
// Index of the th in the header tr that stores where the attribute
|
87
|
-
// data-class="expand"
|
88
|
-
// is defined.
|
89
|
-
this.expandColumn = undefined;
|
90
|
-
// Stores original breakpoint defitions
|
91
|
-
this.origBreakpointsDefs = undefined;
|
92
|
-
// Stores the break points defined in the table header.
|
93
|
-
// Each th in the header tr may contain an optional attribute like
|
94
|
-
// data-hide="phone,tablet"
|
95
|
-
// These attributes and the breakpoints object will be used to create this
|
96
|
-
// object.
|
97
|
-
this.breakpoints = {
|
98
|
-
/**
|
99
|
-
* We will be generating data in the following format:
|
100
|
-
* phone : {
|
101
|
-
* lowerLimit : undefined,
|
102
|
-
* upperLimit : 320,
|
103
|
-
* columnsToHide: []
|
104
|
-
* },
|
105
|
-
* tablet: {
|
106
|
-
* lowerLimit : 320,
|
107
|
-
* upperLimit : 724,
|
108
|
-
* columnsToHide: []
|
109
|
-
* }
|
110
|
-
*/
|
111
|
-
};
|
112
|
-
|
113
|
-
// Store default options
|
114
|
-
this.options = {
|
115
|
-
hideEmptyColumnsInRowDetail: false,
|
116
|
-
clickOn: 'icon',
|
117
|
-
showDetail: null,
|
118
|
-
hideDetail: null
|
119
|
-
};
|
120
|
-
|
121
|
-
// Expand icon template
|
122
|
-
this.expandIconTemplate = '<span class="responsiveExpander"></span>';
|
123
|
-
|
124
|
-
// Row template
|
125
|
-
this.rowTemplate = '<tr class="row-detail"><td><ul><!--column item--></ul></td></tr>';
|
126
|
-
this.rowLiTemplate = '<li><span class="columnTitle"><!--column title--></span>: <span class="columnValue"><!--column value--></span></li>';
|
127
|
-
|
128
|
-
// Responsive behavior on/off flag
|
129
|
-
this.disabled = true;
|
130
|
-
|
131
|
-
// Skip next windows width change flag
|
132
|
-
this.skipNextWindowsWidthChange = false;
|
133
|
-
|
134
|
-
// Initialize settings
|
135
|
-
this.init(breakpoints, options);
|
136
|
-
}
|
137
|
-
|
138
|
-
/**
|
139
|
-
* Responsive datatables helper init function.
|
140
|
-
* Builds breakpoint limits for columns and begins to listen to window resize
|
141
|
-
* event.
|
142
|
-
*
|
143
|
-
* See constructor for the breakpoints parameter.
|
144
|
-
*
|
145
|
-
* @param {Object} breakpoints
|
146
|
-
* @param {Object} options
|
147
|
-
*/
|
148
|
-
ResponsiveDatatablesHelper.prototype.init = function (breakpoints, options) {
|
149
|
-
this.origBreakpointsDefs = breakpoints;
|
150
|
-
this.initBreakpoints();
|
151
|
-
|
152
|
-
// Enable responsive behavior.
|
153
|
-
this.disable(false);
|
154
|
-
|
155
|
-
// Extend options
|
156
|
-
$.extend(this.options, options);
|
75
|
+
var Responsive = function ( settings, opts ) {
|
76
|
+
// Sanity check that we are using DataTables 1.10 or newer
|
77
|
+
if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.1' ) ) {
|
78
|
+
throw 'DataTables Responsive requires DataTables 1.10.1 or newer';
|
79
|
+
}
|
80
|
+
|
81
|
+
this.s = {
|
82
|
+
dt: new DataTable.Api( settings ),
|
83
|
+
columns: []
|
84
|
+
};
|
85
|
+
|
86
|
+
// Check if responsive has already been initialised on this table
|
87
|
+
if ( this.s.dt.settings()[0].responsive ) {
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
|
91
|
+
// details is an object, but for simplicity the user can give it as a string
|
92
|
+
if ( opts && typeof opts.details === 'string' ) {
|
93
|
+
opts.details = { type: opts.details };
|
94
|
+
}
|
95
|
+
|
96
|
+
this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
|
97
|
+
settings.responsive = this;
|
98
|
+
this._constructor();
|
157
99
|
};
|
158
100
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
101
|
+
Responsive.prototype = {
|
102
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
103
|
+
* Constructor
|
104
|
+
*/
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Initialise the Responsive instance
|
108
|
+
*
|
109
|
+
* @private
|
110
|
+
*/
|
111
|
+
_constructor: function ()
|
112
|
+
{
|
113
|
+
var that = this;
|
114
|
+
var dt = this.s.dt;
|
115
|
+
|
116
|
+
dt.settings()[0]._responsive = this;
|
117
|
+
|
118
|
+
// Use DataTables' private throttle function to avoid processor thrashing
|
119
|
+
$(window).on( 'resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle( function () {
|
120
|
+
that._resize();
|
121
|
+
} ) );
|
122
|
+
|
123
|
+
// Destroy event handler
|
124
|
+
dt.on( 'destroy.dtr', function () {
|
125
|
+
$(window).off( 'resize.dtr orientationchange.dtr' );
|
126
|
+
} );
|
127
|
+
|
128
|
+
// Reorder the breakpoints array here in case they have been added out
|
129
|
+
// of order
|
130
|
+
this.c.breakpoints.sort( function (a, b) {
|
131
|
+
return a.width < b.width ? 1 :
|
132
|
+
a.width > b.width ? -1 : 0;
|
133
|
+
} );
|
134
|
+
|
135
|
+
// Determine which columns are already hidden, and should therefore
|
136
|
+
// remain hidden. TODO - should this be done? See thread 22677
|
137
|
+
//
|
138
|
+
// this.s.alwaysHidden = dt.columns(':hidden').indexes();
|
139
|
+
|
140
|
+
this._classLogic();
|
141
|
+
this._resizeAuto();
|
142
|
+
|
143
|
+
// First pass - draw the table for the current viewport size
|
144
|
+
this._resize();
|
145
|
+
|
146
|
+
// Details handler
|
147
|
+
var details = this.c.details;
|
148
|
+
if ( details.type ) {
|
149
|
+
that._detailsInit();
|
150
|
+
this._detailsVis();
|
151
|
+
|
152
|
+
dt.on( 'column-visibility.dtr', function () {
|
153
|
+
that._detailsVis();
|
154
|
+
} );
|
155
|
+
|
156
|
+
$(dt.table().node()).addClass( 'dtr-'+details.type );
|
157
|
+
}
|
158
|
+
},
|
159
|
+
|
160
|
+
|
161
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
162
|
+
* Private methods
|
163
|
+
*/
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Calculate the visibility for the columns in a table for a given
|
167
|
+
* breakpoint. The result is pre-determined based on the class logic if
|
168
|
+
* class names are used to control all columns, but the width of the table
|
169
|
+
* is also used if there are columns which are to be automatically shown
|
170
|
+
* and hidden.
|
171
|
+
*
|
172
|
+
* @param {string} breakpoint Breakpoint name to use for the calculation
|
173
|
+
* @return {array} Array of boolean values initiating the visibility of each
|
174
|
+
* column.
|
175
|
+
* @private
|
176
|
+
*/
|
177
|
+
_columnsVisiblity: function ( breakpoint )
|
178
|
+
{
|
179
|
+
var dt = this.s.dt;
|
180
|
+
var columns = this.s.columns;
|
181
|
+
var i, ien;
|
182
|
+
|
183
|
+
// Class logic - determine which columns are in this breakpoint based
|
184
|
+
// on the classes. If no class control (i.e. `auto`) then `-` is used
|
185
|
+
// to indicate this to the rest of the function
|
186
|
+
var display = $.map( columns, function ( col ) {
|
187
|
+
return col.auto && col.minWidth === null ?
|
188
|
+
false :
|
189
|
+
col.auto === true ?
|
190
|
+
'-' :
|
191
|
+
$.inArray( breakpoint, col.includeIn ) !== -1;
|
192
|
+
} );
|
193
|
+
|
194
|
+
// Auto column control - first pass: how much width is taken by the
|
195
|
+
// ones that must be included from the non-auto columns
|
196
|
+
var requiredWidth = 0;
|
197
|
+
for ( i=0, ien=display.length ; i<ien ; i++ ) {
|
198
|
+
if ( display[i] === true ) {
|
199
|
+
requiredWidth += columns[i].minWidth;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
// Second pass, use up any remaining width for other columns
|
204
|
+
var widthAvailable = dt.table().container().offsetWidth;
|
205
|
+
var usedWidth = widthAvailable - requiredWidth;
|
206
|
+
|
207
|
+
for ( i=0, ien=display.length ; i<ien ; i++ ) {
|
208
|
+
// Control column needs to always be included. This makes it sub-
|
209
|
+
// optimal in terms of using the available with, but to stop layout
|
210
|
+
// thrashing or overflow
|
211
|
+
if ( columns[i].control ) {
|
212
|
+
usedWidth -= columns[i].minWidth;
|
213
|
+
}
|
214
|
+
else if ( display[i] === '-' ) {
|
215
|
+
// Otherwise, remove the width
|
216
|
+
display[i] = usedWidth - columns[i].minWidth < 0 ?
|
217
|
+
false :
|
218
|
+
true;
|
219
|
+
|
220
|
+
// Continue counting down the width, so a smaller column to the
|
221
|
+
// left won't be shown
|
222
|
+
usedWidth -= columns[i].minWidth;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
// Determine if the 'control' column should be shown (if there is one).
|
227
|
+
// This is the case when there is a hidden column (that is not the
|
228
|
+
// control column). The two loops look inefficient here, but they are
|
229
|
+
// trivial and will fly through. We need to know the outcome from the
|
230
|
+
// first , before the action in the second can be taken
|
231
|
+
var showControl = false;
|
232
|
+
|
233
|
+
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
234
|
+
if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
|
235
|
+
showControl = true;
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
241
|
+
if ( columns[i].control ) {
|
242
|
+
display[i] = showControl;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
// Finally we need to make sure that there is at least one column that
|
247
|
+
// is visible
|
248
|
+
if ( $.inArray( true, display ) === -1 ) {
|
249
|
+
display[0] = true;
|
250
|
+
}
|
251
|
+
|
252
|
+
return display;
|
253
|
+
},
|
254
|
+
|
255
|
+
|
256
|
+
/**
|
257
|
+
* Create the internal `columns` array with information about the columns
|
258
|
+
* for the table. This includes determining which breakpoints the column
|
259
|
+
* will appear in, based upon class names in the column, which makes up the
|
260
|
+
* vast majority of this method.
|
261
|
+
*
|
262
|
+
* @private
|
263
|
+
*/
|
264
|
+
_classLogic: function ()
|
265
|
+
{
|
266
|
+
var that = this;
|
267
|
+
var calc = {};
|
268
|
+
var breakpoints = this.c.breakpoints;
|
269
|
+
var columns = this.s.dt.columns().eq(0).map( function (i) {
|
270
|
+
var className = this.column(i).header().className;
|
271
|
+
|
272
|
+
return {
|
273
|
+
className: className,
|
274
|
+
includeIn: [],
|
275
|
+
auto: false,
|
276
|
+
control: false,
|
277
|
+
never: className.match(/\bnever\b/) ? true : false
|
278
|
+
};
|
279
|
+
} );
|
280
|
+
|
281
|
+
// Simply add a breakpoint to `includeIn` array, ensuring that there are
|
282
|
+
// no duplicates
|
283
|
+
var add = function ( colIdx, name ) {
|
284
|
+
var includeIn = columns[ colIdx ].includeIn;
|
285
|
+
|
286
|
+
if ( $.inArray( name, includeIn ) === -1 ) {
|
287
|
+
includeIn.push( name );
|
288
|
+
}
|
289
|
+
};
|
290
|
+
|
291
|
+
var column = function ( colIdx, name, operator, matched ) {
|
292
|
+
var size, i, ien;
|
293
|
+
|
294
|
+
if ( ! operator ) {
|
295
|
+
columns[ colIdx ].includeIn.push( name );
|
296
|
+
}
|
297
|
+
else if ( operator === 'max-' ) {
|
298
|
+
// Add this breakpoint and all smaller
|
299
|
+
size = that._find( name ).width;
|
300
|
+
|
301
|
+
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
302
|
+
if ( breakpoints[i].width <= size ) {
|
303
|
+
add( colIdx, breakpoints[i].name );
|
304
|
+
}
|
305
|
+
}
|
306
|
+
}
|
307
|
+
else if ( operator === 'min-' ) {
|
308
|
+
// Add this breakpoint and all larger
|
309
|
+
size = that._find( name ).width;
|
310
|
+
|
311
|
+
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
312
|
+
if ( breakpoints[i].width >= size ) {
|
313
|
+
add( colIdx, breakpoints[i].name );
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
else if ( operator === 'not-' ) {
|
318
|
+
// Add all but this breakpoint (xxx need extra information)
|
319
|
+
|
320
|
+
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
321
|
+
if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
|
322
|
+
add( colIdx, breakpoints[i].name );
|
323
|
+
}
|
324
|
+
}
|
325
|
+
}
|
326
|
+
};
|
327
|
+
|
328
|
+
// Loop over each column and determine if it has a responsive control
|
329
|
+
// class
|
330
|
+
columns.each( function ( col, i ) {
|
331
|
+
var classNames = col.className.split(' ');
|
332
|
+
var hasClass = false;
|
333
|
+
|
334
|
+
// Split the class name up so multiple rules can be applied if needed
|
335
|
+
for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
|
336
|
+
var className = $.trim( classNames[k] );
|
337
|
+
|
338
|
+
if ( className === 'all' ) {
|
339
|
+
// Include in all
|
340
|
+
hasClass = true;
|
341
|
+
col.includeIn = $.map( breakpoints, function (a) {
|
342
|
+
return a.name;
|
343
|
+
} );
|
344
|
+
return;
|
345
|
+
}
|
346
|
+
else if ( className === 'none' || className === 'never' ) {
|
347
|
+
// Include in none (default) and no auto
|
348
|
+
hasClass = true;
|
349
|
+
return;
|
350
|
+
}
|
351
|
+
else if ( className === 'control' ) {
|
352
|
+
// Special column that is only visible, when one of the other
|
353
|
+
// columns is hidden. This is used for the details control
|
354
|
+
hasClass = true;
|
355
|
+
col.control = true;
|
356
|
+
return;
|
357
|
+
}
|
358
|
+
|
359
|
+
$.each( breakpoints, function ( j, breakpoint ) {
|
360
|
+
// Does this column have a class that matches this breakpoint?
|
361
|
+
var brokenPoint = breakpoint.name.split('-');
|
362
|
+
var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
|
363
|
+
var match = className.match( re );
|
364
|
+
|
365
|
+
if ( match ) {
|
366
|
+
hasClass = true;
|
367
|
+
|
368
|
+
if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
|
369
|
+
// Class name matches breakpoint name fully
|
370
|
+
column( i, breakpoint.name, match[1], match[2]+match[3] );
|
371
|
+
}
|
372
|
+
else if ( match[2] === brokenPoint[0] && ! match[3] ) {
|
373
|
+
// Class name matched primary breakpoint name with no qualifier
|
374
|
+
column( i, breakpoint.name, match[1], match[2] );
|
375
|
+
}
|
376
|
+
}
|
377
|
+
} );
|
378
|
+
}
|
379
|
+
|
380
|
+
// If there was no control class, then automatic sizing is used
|
381
|
+
if ( ! hasClass ) {
|
382
|
+
col.auto = true;
|
383
|
+
}
|
384
|
+
} );
|
385
|
+
|
386
|
+
this.s.columns = columns;
|
387
|
+
},
|
388
|
+
|
389
|
+
|
390
|
+
/**
|
391
|
+
* Initialisation for the details handler
|
392
|
+
*
|
393
|
+
* @private
|
394
|
+
*/
|
395
|
+
_detailsInit: function ()
|
396
|
+
{
|
397
|
+
var that = this;
|
398
|
+
var dt = this.s.dt;
|
399
|
+
var details = this.c.details;
|
400
|
+
|
401
|
+
// The inline type always uses the first child as the target
|
402
|
+
if ( details.type === 'inline' ) {
|
403
|
+
details.target = 'td:first-child';
|
404
|
+
}
|
405
|
+
|
406
|
+
// type.target can be a string jQuery selector or a column index
|
407
|
+
var target = details.target;
|
408
|
+
var selector = typeof target === 'string' ? target : 'td';
|
409
|
+
|
410
|
+
// Click handler to show / hide the details rows when they are available
|
411
|
+
$( dt.table().body() ).on( 'click', selector, function (e) {
|
412
|
+
// If the table is not collapsed (i.e. there is no hidden columns)
|
413
|
+
// then take no action
|
414
|
+
if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
|
415
|
+
return;
|
416
|
+
}
|
417
|
+
|
418
|
+
// Check that the row is actually a DataTable's controlled node
|
419
|
+
if ( ! dt.row( $(this).closest('tr') ).length ) {
|
420
|
+
return;
|
421
|
+
}
|
422
|
+
|
423
|
+
// For column index, we determine if we should act or not in the
|
424
|
+
// handler - otherwise it is already okay
|
425
|
+
if ( typeof target === 'number' ) {
|
426
|
+
var targetIdx = target < 0 ?
|
427
|
+
dt.columns().eq(0).length + target :
|
428
|
+
target;
|
429
|
+
|
430
|
+
if ( dt.cell( this ).index().column !== targetIdx ) {
|
431
|
+
return;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
// $().closest() includes itself in its check
|
436
|
+
var row = dt.row( $(this).closest('tr') );
|
437
|
+
|
438
|
+
if ( row.child.isShown() ) {
|
439
|
+
row.child( false );
|
440
|
+
$( row.node() ).removeClass( 'parent' );
|
441
|
+
}
|
442
|
+
else {
|
443
|
+
var info = that.c.details.renderer( dt, row[0] );
|
444
|
+
row.child( info, 'child' ).show();
|
445
|
+
$( row.node() ).addClass( 'parent' );
|
446
|
+
}
|
447
|
+
} );
|
448
|
+
},
|
449
|
+
|
450
|
+
|
451
|
+
/**
|
452
|
+
* Update the child rows in the table whenever the column visibility changes
|
453
|
+
*
|
454
|
+
* @private
|
455
|
+
*/
|
456
|
+
_detailsVis: function ()
|
457
|
+
{
|
458
|
+
var that = this;
|
459
|
+
var dt = this.s.dt;
|
460
|
+
|
461
|
+
// Find how many columns are hidden
|
462
|
+
var hiddenColumns = dt.columns().indexes().filter( function ( idx ) {
|
463
|
+
var col = dt.column( idx );
|
464
|
+
|
465
|
+
if ( col.visible() ) {
|
466
|
+
return null;
|
467
|
+
}
|
468
|
+
|
469
|
+
// Only counts as hidden if it doesn't have the `never` class
|
470
|
+
return $( col.header() ).hasClass( 'never' ) ? null : idx;
|
471
|
+
} );
|
472
|
+
var haveHidden = true;
|
473
|
+
|
474
|
+
if ( hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[ hiddenColumns[0] ].control ) ) {
|
475
|
+
haveHidden = false;
|
476
|
+
}
|
477
|
+
|
478
|
+
if ( haveHidden ) {
|
479
|
+
// Got hidden columns
|
480
|
+
$( dt.table().node() ).addClass('collapsed');
|
481
|
+
|
482
|
+
// Show all existing child rows
|
483
|
+
dt.rows().eq(0).each( function (idx) {
|
484
|
+
var row = dt.row( idx );
|
485
|
+
|
486
|
+
if ( row.child() ) {
|
487
|
+
var info = that.c.details.renderer( dt, row[0] );
|
488
|
+
|
489
|
+
// The renderer can return false to have no child row
|
490
|
+
if ( info === false ) {
|
491
|
+
row.child.hide();
|
492
|
+
}
|
493
|
+
else {
|
494
|
+
row.child( info, 'child' ).show();
|
495
|
+
}
|
496
|
+
}
|
497
|
+
} );
|
498
|
+
}
|
499
|
+
else {
|
500
|
+
// No hidden columns
|
501
|
+
$( dt.table().node() ).removeClass('collapsed');
|
502
|
+
|
503
|
+
// Hide all existing child rows
|
504
|
+
dt.rows().eq(0).each( function (idx) {
|
505
|
+
dt.row( idx ).child.hide();
|
506
|
+
} );
|
507
|
+
}
|
508
|
+
},
|
509
|
+
|
510
|
+
|
511
|
+
/**
|
512
|
+
* Find a breakpoint object from a name
|
513
|
+
* @param {string} name Breakpoint name to find
|
514
|
+
* @return {object} Breakpoint description object
|
515
|
+
*/
|
516
|
+
_find: function ( name )
|
517
|
+
{
|
518
|
+
var breakpoints = this.c.breakpoints;
|
519
|
+
|
520
|
+
for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
521
|
+
if ( breakpoints[i].name === name ) {
|
522
|
+
return breakpoints[i];
|
523
|
+
}
|
524
|
+
}
|
525
|
+
},
|
526
|
+
|
527
|
+
|
528
|
+
/**
|
529
|
+
* Alter the table display for a resized viewport. This involves first
|
530
|
+
* determining what breakpoint the window currently is in, getting the
|
531
|
+
* column visibilities to apply and then setting them.
|
532
|
+
*
|
533
|
+
* @private
|
534
|
+
*/
|
535
|
+
_resize: function ()
|
536
|
+
{
|
537
|
+
var dt = this.s.dt;
|
538
|
+
var width = $(window).width();
|
539
|
+
var breakpoints = this.c.breakpoints;
|
540
|
+
var breakpoint = breakpoints[0].name;
|
541
|
+
|
542
|
+
// Determine what breakpoint we are currently at
|
543
|
+
for ( var i=breakpoints.length-1 ; i>=0 ; i-- ) {
|
544
|
+
if ( width <= breakpoints[i].width ) {
|
545
|
+
breakpoint = breakpoints[i].name;
|
546
|
+
break;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
|
550
|
+
// Show the columns for that break point
|
551
|
+
var columns = this._columnsVisiblity( breakpoint );
|
552
|
+
|
553
|
+
dt.columns().eq(0).each( function ( colIdx, i ) {
|
554
|
+
dt.column( colIdx ).visible( columns[i] );
|
555
|
+
} );
|
556
|
+
},
|
557
|
+
|
558
|
+
|
559
|
+
/**
|
560
|
+
* Determine the width of each column in the table so the auto column hiding
|
561
|
+
* has that information to work with. This method is never going to be 100%
|
562
|
+
* perfect since column widths can change slightly per page, but without
|
563
|
+
* seriously compromising performance this is quite effective.
|
564
|
+
*
|
565
|
+
* @private
|
566
|
+
*/
|
567
|
+
_resizeAuto: function ()
|
568
|
+
{
|
569
|
+
var dt = this.s.dt;
|
570
|
+
var columns = this.s.columns;
|
571
|
+
|
572
|
+
// Are we allowed to do auto sizing?
|
573
|
+
if ( ! this.c.auto ) {
|
574
|
+
return;
|
575
|
+
}
|
576
|
+
|
577
|
+
// Are there any columns that actually need auto-sizing, or do they all
|
578
|
+
// have classes defined
|
579
|
+
if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
|
580
|
+
return;
|
581
|
+
}
|
582
|
+
|
583
|
+
// Clone the table with the current data in it
|
584
|
+
var tableWidth = dt.table().node().offsetWidth;
|
585
|
+
var columnWidths = dt.columns;
|
586
|
+
var clonedTable = dt.table().node().cloneNode( false );
|
587
|
+
var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
|
588
|
+
var clonedBody = $( dt.table().body().cloneNode( false ) ).appendTo( clonedTable );
|
589
|
+
|
590
|
+
// This is a bit slow, but we need to get a clone of each row that
|
591
|
+
// includes all columns. As such, try to do this as little as possible.
|
592
|
+
dt.rows( { page: 'current' } ).indexes().flatten().each( function ( idx ) {
|
593
|
+
var clone = dt.row( idx ).node().cloneNode( true );
|
594
|
+
|
595
|
+
if ( dt.columns( ':hidden' ).flatten().length ) {
|
596
|
+
$(clone).append( dt.cells( idx, ':hidden' ).nodes().to$().clone() );
|
597
|
+
}
|
598
|
+
|
599
|
+
$(clone).appendTo( clonedBody );
|
600
|
+
} );
|
601
|
+
|
602
|
+
var cells = dt.columns().header().to$().clone( false ).wrapAll('tr').appendTo( clonedHeader );
|
603
|
+
var inserted = $('<div/>')
|
604
|
+
.css( {
|
605
|
+
width: 1,
|
606
|
+
height: 1,
|
607
|
+
overflow: 'hidden'
|
608
|
+
} )
|
609
|
+
.append( clonedTable )
|
610
|
+
.insertBefore( dt.table().node() );
|
611
|
+
|
612
|
+
// The cloned header now contains the smallest that each column can be
|
613
|
+
dt.columns().eq(0).each( function ( idx ) {
|
614
|
+
columns[idx].minWidth = cells[ idx ].offsetWidth || 0;
|
615
|
+
} );
|
616
|
+
|
617
|
+
inserted.remove();
|
618
|
+
}
|
255
619
|
};
|
256
620
|
|
621
|
+
|
257
622
|
/**
|
258
|
-
*
|
623
|
+
* List of default breakpoints. Each item in the array is an object with two
|
624
|
+
* properties:
|
625
|
+
*
|
626
|
+
* * `name` - the breakpoint name.
|
627
|
+
* * `width` - the breakpoint width
|
259
628
|
*
|
260
|
-
* @
|
629
|
+
* @name Responsive.breakpoints
|
630
|
+
* @static
|
261
631
|
*/
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
$(window).bind("resize", function () {
|
270
|
-
that.respond();
|
271
|
-
});
|
272
|
-
} else {
|
273
|
-
$(window).unbind("resize");
|
274
|
-
}
|
275
|
-
};
|
632
|
+
Responsive.breakpoints = [
|
633
|
+
{ name: 'desktop', width: Infinity },
|
634
|
+
{ name: 'tablet-l', width: 1024 },
|
635
|
+
{ name: 'tablet-p', width: 768 },
|
636
|
+
{ name: 'mobile-l', width: 480 },
|
637
|
+
{ name: 'mobile-p', width: 320 }
|
638
|
+
];
|
276
639
|
|
277
|
-
/**
|
278
|
-
* Respond window size change. This helps make datatables responsive.
|
279
|
-
*/
|
280
|
-
ResponsiveDatatablesHelper.prototype.respond = function () {
|
281
|
-
if (this.disabled) {
|
282
|
-
return;
|
283
|
-
}
|
284
|
-
var that = this;
|
285
|
-
|
286
|
-
// Get new windows width
|
287
|
-
var newWindowWidth = $(window).width();
|
288
|
-
|
289
|
-
// Loop through breakpoints to see which columns need to be shown/hidden.
|
290
|
-
var newColumnsToHide = [];
|
291
|
-
|
292
|
-
for (var prop in this.breakpoints) {
|
293
|
-
var element = this.breakpoints[prop];
|
294
|
-
if ((!element.lowerLimit || newWindowWidth > element.lowerLimit) && (!element.upperLimit || newWindowWidth <= element.upperLimit)) {
|
295
|
-
this.currentBreakpoint = element.name;
|
296
|
-
newColumnsToHide = element.columnsToHide;
|
297
|
-
}
|
298
|
-
}
|
299
|
-
|
300
|
-
// Find out if a column show/hide should happen.
|
301
|
-
// Skip column show/hide if this window width change follows immediately
|
302
|
-
// after a previous column show/hide. This will help prevent a loop.
|
303
|
-
var columnShowHide = false;
|
304
|
-
if (!this.skipNextWindowsWidthChange) {
|
305
|
-
// Check difference in length
|
306
|
-
if (this.lastBreakpoint.length === 0 && newColumnsToHide.length) {
|
307
|
-
// No previous breakpoint and new breakpoint
|
308
|
-
columnShowHide = true;
|
309
|
-
} else if (this.lastBreakpoint != this.currentBreakpoint) {
|
310
|
-
// Different breakpoints
|
311
|
-
columnShowHide = true;
|
312
|
-
} else if (this.columnsHiddenIndexes.length !== newColumnsToHide.length) {
|
313
|
-
// Difference in number of hidden columns
|
314
|
-
columnShowHide = true;
|
315
|
-
} else {
|
316
|
-
// Possible same number of columns but check for difference in columns
|
317
|
-
var d1 = this.difference(this.columnsHiddenIndexes, newColumnsToHide).length;
|
318
|
-
var d2 = this.difference(newColumnsToHide, this.columnsHiddenIndexes).length;
|
319
|
-
columnShowHide = d1 + d2 > 0;
|
320
|
-
}
|
321
|
-
}
|
322
|
-
|
323
|
-
if (columnShowHide) {
|
324
|
-
// Showing/hiding a column at breakpoint may cause a windows width
|
325
|
-
// change. Let's flag to skip the column show/hide that may be
|
326
|
-
// caused by the next windows width change.
|
327
|
-
this.skipNextWindowsWidthChange = true;
|
328
|
-
this.columnsHiddenIndexes = newColumnsToHide;
|
329
|
-
this.columnsShownIndexes = this.difference(this.columnIndexes, this.columnsHiddenIndexes);
|
330
|
-
this.showHideColumns();
|
331
|
-
this.lastBreakpoint = this.currentBreakpoint;
|
332
|
-
this.setState();
|
333
|
-
this.skipNextWindowsWidthChange = false;
|
334
|
-
}
|
335
|
-
|
336
|
-
|
337
|
-
// We don't skip this part.
|
338
|
-
// If one or more columns have been hidden, add the has-columns-hidden class to table.
|
339
|
-
// This class will show what state the table is in.
|
340
|
-
if (this.columnsHiddenIndexes.length) {
|
341
|
-
this.tableElement.addClass('has-columns-hidden');
|
342
|
-
|
343
|
-
// Show details for each row that is tagged with the class .detail-show.
|
344
|
-
$('tr.detail-show', this.tableElement).each(function (index, element) {
|
345
|
-
var tr = $(element);
|
346
|
-
if (tr.next('.row-detail').length === 0) {
|
347
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(that, tr);
|
348
|
-
}
|
349
|
-
});
|
350
|
-
} else {
|
351
|
-
this.tableElement.removeClass('has-columns-hidden');
|
352
|
-
$('tr.row-detail').each(function (event) {
|
353
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail(that, $(this).prev());
|
354
|
-
});
|
355
|
-
}
|
356
|
-
};
|
357
640
|
|
358
641
|
/**
|
359
|
-
*
|
360
|
-
*/
|
361
|
-
ResponsiveDatatablesHelper.prototype.showHideColumns = function () {
|
362
|
-
// Calculate the columns to show
|
363
|
-
// Show columns that may have been previously hidden.
|
364
|
-
for (var i = 0, l = this.columnsShownIndexes.length; i < l; i++) {
|
365
|
-
this.api.column(this.columnsShownIndexes[i]).visible(true);
|
366
|
-
}
|
367
|
-
|
368
|
-
// Hide columns that may have been previously shown.
|
369
|
-
for (var i = 0, l = this.columnsHiddenIndexes.length; i < l; i++) {
|
370
|
-
this.api.column(this.columnsHiddenIndexes[i]).visible(false);
|
371
|
-
}
|
372
|
-
|
373
|
-
// Rebuild details to reflect shown/hidden column changes.
|
374
|
-
var that = this;
|
375
|
-
$('tr.row-detail').each(function () {
|
376
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail(that, $(this).prev());
|
377
|
-
});
|
378
|
-
if (this.tableElement.hasClass('has-columns-hidden')) {
|
379
|
-
$('tr.detail-show', this.tableElement).each(function (index, element) {
|
380
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(that, $(element));
|
381
|
-
});
|
382
|
-
}
|
383
|
-
};
|
384
|
-
|
385
|
-
/**
|
386
|
-
* Create the expand icon on the column with the data-class="expand" attribute
|
387
|
-
* defined for it's header.
|
642
|
+
* Responsive default settings for initialisation
|
388
643
|
*
|
389
|
-
* @
|
644
|
+
* @namespace
|
645
|
+
* @name Responsive.defaults
|
646
|
+
* @static
|
390
647
|
*/
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
648
|
+
Responsive.defaults = {
|
649
|
+
/**
|
650
|
+
* List of breakpoints for the instance. Note that this means that each
|
651
|
+
* instance can have its own breakpoints. Additionally, the breakpoints
|
652
|
+
* cannot be changed once an instance has been creased.
|
653
|
+
*
|
654
|
+
* @type {Array}
|
655
|
+
* @default Takes the value of `Responsive.breakpoints`
|
656
|
+
*/
|
657
|
+
breakpoints: Responsive.breakpoints,
|
658
|
+
|
659
|
+
/**
|
660
|
+
* Enable / disable auto hiding calculations. It can help to increase
|
661
|
+
* performance slightly if you disable this option, but all columns would
|
662
|
+
* need to have breakpoint classes assigned to them
|
663
|
+
*
|
664
|
+
* @type {Boolean}
|
665
|
+
* @default `true`
|
666
|
+
*/
|
667
|
+
auto: true,
|
668
|
+
|
669
|
+
/**
|
670
|
+
* Details control. If given as a string value, the `type` property of the
|
671
|
+
* default object is set to that value, and the defaults used for the rest
|
672
|
+
* of the object - this is for ease of implementation.
|
673
|
+
*
|
674
|
+
* The object consists of the following properties:
|
675
|
+
*
|
676
|
+
* * `renderer` - function that is called for display of the child row data.
|
677
|
+
* The default function will show the data from the hidden columns
|
678
|
+
* * `target` - Used as the selector for what objects to attach the child
|
679
|
+
* open / close to
|
680
|
+
* * `type` - `false` to disable the details display, `inline` or `column`
|
681
|
+
* for the two control types
|
682
|
+
*
|
683
|
+
* @type {Object|string}
|
684
|
+
*/
|
685
|
+
details: {
|
686
|
+
renderer: function ( api, rowIdx ) {
|
687
|
+
var data = api.cells( rowIdx, ':hidden' ).eq(0).map( function ( cell ) {
|
688
|
+
var header = $( api.column( cell.column ).header() );
|
689
|
+
var idx = api.cell( cell ).index();
|
690
|
+
|
691
|
+
if ( header.hasClass( 'control' ) || header.hasClass( 'never' ) ) {
|
692
|
+
return '';
|
693
|
+
}
|
694
|
+
|
695
|
+
// Use a non-public DT API method to render the data for display
|
696
|
+
// This needs to be updated when DT adds a suitable method for
|
697
|
+
// this type of data retrieval
|
698
|
+
var dtPrivate = api.settings()[0];
|
699
|
+
var cellData = dtPrivate.oApi._fnGetCellData(
|
700
|
+
dtPrivate, idx.row, idx.column, 'display'
|
701
|
+
);
|
702
|
+
|
703
|
+
return '<li data-dtr-index="'+idx.column+'">'+
|
704
|
+
'<span class="dtr-title">'+
|
705
|
+
header.text()+':'+
|
706
|
+
'</span> '+
|
707
|
+
'<span class="dtr-data">'+
|
708
|
+
cellData+
|
709
|
+
'</span>'+
|
710
|
+
'</li>';
|
711
|
+
} ).toArray().join('');
|
712
|
+
|
713
|
+
return data ?
|
714
|
+
$('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
|
715
|
+
false;
|
716
|
+
},
|
717
|
+
|
718
|
+
target: 0,
|
719
|
+
|
720
|
+
type: 'inline'
|
721
|
+
}
|
426
722
|
};
|
427
723
|
|
428
|
-
/**
|
429
|
-
* Show row detail event handler.
|
430
|
-
*
|
431
|
-
* This handler is used to handle the click event of the expand icon defined in
|
432
|
-
* the table row data element.
|
433
|
-
*
|
434
|
-
* @param {Object} event jQuery event object
|
435
|
-
*/
|
436
|
-
ResponsiveDatatablesHelper.prototype.showRowDetailEventHandler = function (event) {
|
437
|
-
var responsiveDatatablesHelperInstance = event.data.responsiveDatatablesHelperInstance;
|
438
|
-
if (responsiveDatatablesHelperInstance.disabled) {
|
439
|
-
return;
|
440
|
-
}
|
441
724
|
|
442
|
-
|
725
|
+
/*
|
726
|
+
* API
|
727
|
+
*/
|
728
|
+
var Api = $.fn.dataTable.Api;
|
443
729
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
730
|
+
// Doesn't do anything - work around for a bug in DT... Not documented
|
731
|
+
Api.register( 'responsive()', function () {
|
732
|
+
return this;
|
733
|
+
} );
|
448
734
|
|
449
|
-
|
450
|
-
|
735
|
+
Api.register( 'responsive.recalc()', function () {
|
736
|
+
this.iterator( 'table', function ( ctx ) {
|
737
|
+
if ( ctx._responsive ) {
|
738
|
+
ctx._responsive._resizeAuto();
|
739
|
+
ctx._responsive._resize();
|
740
|
+
}
|
741
|
+
} );
|
742
|
+
} );
|
451
743
|
|
452
|
-
|
453
|
-
|
454
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail(responsiveDatatablesHelperInstance, tr);
|
455
|
-
} else {
|
456
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(responsiveDatatablesHelperInstance, tr);
|
457
|
-
}
|
744
|
+
Api.register( 'responsive.index()', function ( li ) {
|
745
|
+
li = $(li);
|
458
746
|
|
459
|
-
|
747
|
+
return {
|
748
|
+
column: li.data('dtr-index'),
|
749
|
+
row: li.parent().data('dtr-index')
|
750
|
+
};
|
751
|
+
} );
|
460
752
|
|
461
|
-
// Prevent click event from bubbling up to higher-level DOM elements.
|
462
|
-
event.stopPropagation();
|
463
|
-
};
|
464
753
|
|
465
754
|
/**
|
466
|
-
*
|
755
|
+
* Version information
|
467
756
|
*
|
468
|
-
* @
|
469
|
-
* @
|
757
|
+
* @name Responsive.version
|
758
|
+
* @static
|
470
759
|
*/
|
471
|
-
|
472
|
-
// Get column because we need their titles.
|
473
|
-
var api = responsiveDatatablesHelperInstance.api;
|
474
|
-
var columns = api.columns().header();
|
475
|
-
|
476
|
-
// Create the new tr.
|
477
|
-
var newTr = $(responsiveDatatablesHelperInstance.rowTemplate);
|
478
|
-
|
479
|
-
// Get the ul that we'll insert li's into.
|
480
|
-
var ul = $('ul', newTr);
|
481
|
-
|
482
|
-
// Loop through hidden columns and create an li for each of them.
|
483
|
-
for (var i = 0; i < responsiveDatatablesHelperInstance.columnsHiddenIndexes.length; i++) {
|
484
|
-
var index = responsiveDatatablesHelperInstance.columnsHiddenIndexes[i];
|
485
|
-
|
486
|
-
// Get row td
|
487
|
-
var rowIndex = api.row(tr).index();
|
488
|
-
var td = api.cell(rowIndex, index).node();
|
489
|
-
|
490
|
-
// Don't create li if contents are empty (depends on hideEmptyColumnsInRowDetail option).
|
491
|
-
if (!responsiveDatatablesHelperInstance.options.hideEmptyColumnsInRowDetail || td.innerHTML.trim().length) {
|
492
|
-
var li = $(responsiveDatatablesHelperInstance.rowLiTemplate);
|
493
|
-
var hiddenColumnName = $(columns[index]).attr('data-name');
|
494
|
-
$('.columnTitle', li).html(hiddenColumnName !== undefined ? hiddenColumnName : columns[index].innerHTML);
|
495
|
-
var contents = $(td).contents();
|
496
|
-
var clonedContents = contents.clone();
|
497
|
-
|
498
|
-
// Select elements' selectedIndex are not cloned. Do it manually.
|
499
|
-
for (var n = 0, m = contents.length; n < m; n++) {
|
500
|
-
var node = contents[n];
|
501
|
-
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'SELECT') {
|
502
|
-
clonedContents[n].selectedIndex = node.selectedIndex
|
503
|
-
}
|
504
|
-
}
|
505
|
-
|
506
|
-
// Set the column contents and save the original td source.
|
507
|
-
$('.columnValue', li).append(clonedContents).data('originalTdSource', td);
|
508
|
-
|
509
|
-
// Copy index to data attribute, so we'll know where to put the value when the tr.row-detail is removed.
|
510
|
-
li.attr('data-column', index);
|
511
|
-
|
512
|
-
// Copy td class to new li.
|
513
|
-
var tdClass = $(td).attr('class');
|
514
|
-
if (tdClass !== 'undefined' && tdClass !== false && tdClass !== '') {
|
515
|
-
li.addClass(tdClass)
|
516
|
-
}
|
517
|
-
|
518
|
-
ul.append(li);
|
519
|
-
}
|
520
|
-
}
|
521
|
-
|
522
|
-
// Create tr colspan attribute.
|
523
|
-
var colspan = responsiveDatatablesHelperInstance.columnIndexes.length - responsiveDatatablesHelperInstance.columnsHiddenIndexes.length;
|
524
|
-
newTr.find('> td').attr('colspan', colspan);
|
525
|
-
|
526
|
-
// Append the new tr after the current tr.
|
527
|
-
tr.after(newTr);
|
528
|
-
|
529
|
-
// call the showDetail function if needbe
|
530
|
-
if (responsiveDatatablesHelperInstance.options.showDetail){
|
531
|
-
responsiveDatatablesHelperInstance.options.showDetail(newTr);
|
532
|
-
}
|
533
|
-
};
|
760
|
+
Responsive.version = '1.0.2';
|
534
761
|
|
535
|
-
/**
|
536
|
-
* Hide row details.
|
537
|
-
*
|
538
|
-
* @param {ResponsiveDatatablesHelper} responsiveDatatablesHelperInstance instance of ResponsiveDatatablesHelper
|
539
|
-
* @param {Object} tr jQuery wrapped set
|
540
|
-
*/
|
541
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail = function (responsiveDatatablesHelperInstance, tr) {
|
542
|
-
// If the value of an input has changed while in row detail, we need to copy its state back
|
543
|
-
// to the DataTables object so that value will persist when the tr.row-detail is removed.
|
544
|
-
var rowDetail = tr.next('.row-detail');
|
545
|
-
if (responsiveDatatablesHelperInstance.options.hideDetail){
|
546
|
-
responsiveDatatablesHelperInstance.options.hideDetail(rowDetail);
|
547
|
-
}
|
548
|
-
rowDetail.find('li').each(function () {
|
549
|
-
var columnValueContainer = $(this).find('span.columnValue');
|
550
|
-
var tdContents = columnValueContainer.contents();
|
551
|
-
var td = columnValueContainer.data('originalTdSource');
|
552
|
-
$(td).empty().append(tdContents);
|
553
|
-
});
|
554
|
-
rowDetail.remove();
|
555
|
-
};
|
556
|
-
|
557
|
-
/**
|
558
|
-
* Enable/disable responsive behavior and restores changes made.
|
559
|
-
*
|
560
|
-
* @param {Boolean} disable, default is true
|
561
|
-
*/
|
562
|
-
ResponsiveDatatablesHelper.prototype.disable = function (disable) {
|
563
|
-
this.disabled = (disable === undefined) || disable;
|
564
762
|
|
565
|
-
|
566
|
-
|
567
|
-
this.setWindowsResizeHandler(false);
|
763
|
+
$.fn.dataTable.Responsive = Responsive;
|
764
|
+
$.fn.DataTable.Responsive = Responsive;
|
568
765
|
|
569
|
-
|
570
|
-
|
766
|
+
// Attach a listener to the document which listens for DataTables initialisation
|
767
|
+
// events so we can automatically initialise
|
768
|
+
$(document).on( 'init.dt.dtr', function (e, settings, json) {
|
769
|
+
if ( $(settings.nTable).hasClass( 'responsive' ) ||
|
770
|
+
$(settings.nTable).hasClass( 'dt-responsive' ) ||
|
771
|
+
settings.oInit.responsive ||
|
772
|
+
DataTable.defaults.responsive
|
773
|
+
) {
|
774
|
+
var init = settings.oInit.responsive;
|
571
775
|
|
572
|
-
|
573
|
-
|
776
|
+
if ( init !== false ) {
|
777
|
+
new Responsive( settings, $.isPlainObject( init ) ? init : {} );
|
778
|
+
}
|
779
|
+
}
|
780
|
+
} );
|
574
781
|
|
575
|
-
|
576
|
-
|
782
|
+
return Responsive;
|
783
|
+
}; // /factory
|
577
784
|
|
578
|
-
this.columnsHiddenIndexes = [];
|
579
|
-
this.columnsShownIndexes = this.columnIndexes;
|
580
|
-
this.showHideColumns();
|
581
|
-
this.tableElement.removeClass('has-columns-hidden');
|
582
785
|
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
786
|
+
// Define as an AMD module if possible
|
787
|
+
if ( typeof define === 'function' && define.amd ) {
|
788
|
+
define( ['jquery', 'datatables'], factory );
|
789
|
+
}
|
790
|
+
else if ( typeof exports === 'object' ) {
|
791
|
+
// Node/CommonJS
|
792
|
+
factory( require('jquery'), require('datatables') );
|
793
|
+
}
|
794
|
+
else if ( jQuery && !jQuery.fn.dataTable.Responsive ) {
|
795
|
+
// Otherwise simply initialise as normal, stopping multiple evaluation
|
796
|
+
factory( jQuery, jQuery.fn.dataTable );
|
797
|
+
}
|
589
798
|
|
590
|
-
/**
|
591
|
-
* Get state from cookie.
|
592
|
-
*/
|
593
|
-
ResponsiveDatatablesHelper.prototype.getState = function () {
|
594
|
-
if (typeof(Storage)) {
|
595
|
-
// Use local storage
|
596
|
-
var value = JSON.parse(localStorage.getItem(this.cookieName));
|
597
|
-
if (value) {
|
598
|
-
this.columnIndexes = value.columnIndexes;
|
599
|
-
this.breakpoints = value.breakpoints;
|
600
|
-
this.expandColumn = value.expandColumn;
|
601
|
-
this.lastBreakpoint = value.lastBreakpoint;
|
602
|
-
this.lastStateExists = true;
|
603
|
-
}
|
604
|
-
} else {
|
605
|
-
// No local storage.
|
606
|
-
}
|
607
|
-
};
|
608
799
|
|
609
|
-
|
610
|
-
* Saves state to cookie.
|
611
|
-
*/
|
612
|
-
ResponsiveDatatablesHelper.prototype.setState = function () {
|
613
|
-
if (typeof(Storage)) {
|
614
|
-
// Use local storage
|
615
|
-
var d1 = this.difference(this.lastColumnsHiddenIndexes, this.columnsHiddenIndexes).length;
|
616
|
-
var d2 = this.difference(this.columnsHiddenIndexes, this.lastColumnsHiddenIndexes).length;
|
617
|
-
|
618
|
-
if (d1 + d2 > 0) {
|
619
|
-
var tt;
|
620
|
-
var value = {
|
621
|
-
columnIndexes: this.columnIndexes, // array
|
622
|
-
columnsHiddenIndexes: this.columnsHiddenIndexes, // array
|
623
|
-
breakpoints: this.breakpoints, // object
|
624
|
-
expandColumn: this.expandColumn, // int|undefined
|
625
|
-
lastBreakpoint: this.lastBreakpoint // string
|
626
|
-
};
|
627
|
-
|
628
|
-
localStorage.setItem(this.cookieName, JSON.stringify(value));
|
629
|
-
this.lastColumnsHiddenIndexes = this.columnsHiddenIndexes.slice(0);
|
630
|
-
}
|
631
|
-
} else {
|
632
|
-
// No local storage.
|
633
|
-
}
|
634
|
-
};
|
800
|
+
})(window, document);
|
635
801
|
|
636
|
-
/**
|
637
|
-
* Get Difference.
|
638
|
-
*/
|
639
|
-
ResponsiveDatatablesHelper.prototype.difference = function (a, b) {
|
640
|
-
var arr = [], i, hash = {};
|
641
|
-
for (i = b.length - 1; i >= 0; i--) {
|
642
|
-
hash[b[i]] = true;
|
643
|
-
}
|
644
|
-
for (i = a.length - 1; i >= 0; i--) {
|
645
|
-
if (hash[a[i]] !== true) {
|
646
|
-
arr.push(a[i]);
|
647
|
-
}
|
648
|
-
}
|
649
|
-
return arr;
|
650
|
-
};
|