jquery-datatables-rails 2.1.10.0.0 → 2.1.10.0.2
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/{jquery.dataTables.bootstrap.js → bootstrap/2/jquery.dataTables.bootstrap.js} +0 -0
- data/app/assets/javascripts/dataTables/{jquery.dataTables.bootstrap3.js → bootstrap/3/jquery.dataTables.bootstrap.js} +0 -0
- data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +665 -0
- data/app/assets/stylesheets/dataTables/{jquery.dataTables.bootstrap.css.scss → bootstrap/2/jquery.dataTables.bootstrap.css.scss} +0 -0
- data/app/assets/stylesheets/dataTables/{jquery.dataTables.bootstrap3.css.scss → bootstrap/3/jquery.dataTables.bootstrap.css.scss} +0 -0
- data/app/assets/stylesheets/dataTables/{jquery.dataTables.responsive.css.scss → extras/dataTables.responsive.css.scss} +1 -0
- data/lib/jquery/datatables/rails/version.rb +1 -1
- metadata +9 -8
- data/app/assets/javascripts/dataTables/jquery.dataTables.responsive.js +0 -435
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b12fa79b718f5e292c1c207645a9abda2d5c1bcb
|
4
|
+
data.tar.gz: d98077463717b75843d14425d45da98ba24c8b72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92195cbcdeb6952c8ed1da99bee4c8167304dc66fa06882fc8e978c429d516ee132f9280d222941a01c45a10f575fa444b79c39a13111485ed674097527de94c
|
7
|
+
data.tar.gz: 5d9beb135b396773f73ebbbaccf618b8fb702e4dac2ffd876ecc34b3bc2fac6c15591678d80e0b3f0c1096266f5689a1dc02e6d2f93394afa28ab76b55c74caf
|
File without changes
|
File without changes
|
@@ -0,0 +1,665 @@
|
|
1
|
+
/**
|
2
|
+
* File: datatables.responsive.js
|
3
|
+
* Version: 0.2.0
|
4
|
+
* Author: Seen Sai Yang
|
5
|
+
* Info: https://github.com/Comanche/datatables-responsive
|
6
|
+
*
|
7
|
+
* Copyright 2013 Seen Sai Yang, all rights reserved.
|
8
|
+
*
|
9
|
+
* This source file is free software, under either the GPL v2 license or a
|
10
|
+
* BSD style license.
|
11
|
+
*
|
12
|
+
* This source file is distributed in the hope that it will be useful, but
|
13
|
+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
14
|
+
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
15
|
+
*
|
16
|
+
* You should have received a copy of the GNU General Public License and the
|
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
|
20
|
+
*/
|
21
|
+
|
22
|
+
'use strict';
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Constructor for responsive datables helper.
|
26
|
+
*
|
27
|
+
* This helper class makes datatables responsive to the window size.
|
28
|
+
*
|
29
|
+
* The parameter, breakpoints, is an object for each breakpoint key/value pair
|
30
|
+
* with the following format: { breakpoint_name: pixel_width_at_breakpoint }.
|
31
|
+
*
|
32
|
+
* An example is as follows:
|
33
|
+
*
|
34
|
+
* {
|
35
|
+
* tablet: 1024,
|
36
|
+
* phone: 480
|
37
|
+
* }
|
38
|
+
*
|
39
|
+
* These breakpoint name may be used as possible values for the data-hide
|
40
|
+
* attribute. The data-hide attribute is optional and may be defined for each
|
41
|
+
* th element in the table header.
|
42
|
+
*
|
43
|
+
* The parameter, options, is an object of options supported by the responsive
|
44
|
+
* helper. The following options are supported:
|
45
|
+
*
|
46
|
+
* {
|
47
|
+
* hideEmptyColumnsInRowDetail - Boolean, default: false.
|
48
|
+
* clickOn - icon|cell|row, default: icon
|
49
|
+
* showDetail - function called when detail row shown
|
50
|
+
* hideDetail - function called when detail row hidden
|
51
|
+
* }
|
52
|
+
*
|
53
|
+
* @param {Object|string} tableSelector jQuery wrapped set or selector for
|
54
|
+
* datatables container element.
|
55
|
+
* @param {Object} breakpoints Object defining the responsive
|
56
|
+
* breakpoint for datatables.
|
57
|
+
* @param {Object} options Object of options.
|
58
|
+
*/
|
59
|
+
function ResponsiveDatatablesHelper(tableSelector, breakpoints, options) {
|
60
|
+
if (typeof tableSelector === 'string') {
|
61
|
+
this.tableElement = $(tableSelector);
|
62
|
+
} else {
|
63
|
+
this.tableElement = tableSelector;
|
64
|
+
}
|
65
|
+
|
66
|
+
// Get data table API.
|
67
|
+
this.api = this.tableElement.dataTable().api();
|
68
|
+
|
69
|
+
// State of column indexes and which are shown or hidden.
|
70
|
+
this.columnIndexes = [];
|
71
|
+
this.columnsShownIndexes = [];
|
72
|
+
this.columnsHiddenIndexes = [];
|
73
|
+
this.currentBreakpoint = '';
|
74
|
+
this.lastBreakpoint = '';
|
75
|
+
this.lastColumnsHiddenIndexes = [];
|
76
|
+
|
77
|
+
// Save state
|
78
|
+
var fileName = window.location.pathname.split("/").pop();
|
79
|
+
var context = this.api.settings().context[0];
|
80
|
+
|
81
|
+
this.tableId = context.sTableId;
|
82
|
+
this.saveState = context.oInit.bStateSave;
|
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);
|
157
|
+
};
|
158
|
+
|
159
|
+
ResponsiveDatatablesHelper.prototype.initBreakpoints = function () {
|
160
|
+
// Get last state if it exists
|
161
|
+
if (this.saveState) {
|
162
|
+
this.getState();
|
163
|
+
}
|
164
|
+
|
165
|
+
if (!this.lastStateExists) {
|
166
|
+
/** Generate breakpoints in the format we need. ***********************/
|
167
|
+
// First, we need to create a sorted array of the breakpoints given.
|
168
|
+
var breakpointsSorted = [];
|
169
|
+
|
170
|
+
for (var prop in this.origBreakpointsDefs) {
|
171
|
+
breakpointsSorted.push({
|
172
|
+
name: prop,
|
173
|
+
upperLimit: this.origBreakpointsDefs[prop],
|
174
|
+
columnsToHide: []
|
175
|
+
});
|
176
|
+
}
|
177
|
+
|
178
|
+
breakpointsSorted.sort(function (a, b) {
|
179
|
+
return a.upperLimit - b.upperLimit;
|
180
|
+
});
|
181
|
+
|
182
|
+
// Set lower and upper limits for each breakpoint.
|
183
|
+
var lowerLimit = 0;
|
184
|
+
for (var i = 0; i < breakpointsSorted.length; i++) {
|
185
|
+
breakpointsSorted[i].lowerLimit = lowerLimit;
|
186
|
+
lowerLimit = breakpointsSorted[i].upperLimit;
|
187
|
+
}
|
188
|
+
|
189
|
+
// Add the default breakpoint which shows all (has no upper limit).
|
190
|
+
breakpointsSorted.push({
|
191
|
+
name : 'always',
|
192
|
+
lowerLimit : lowerLimit,
|
193
|
+
upperLimit : Infinity,
|
194
|
+
columnsToHide: []
|
195
|
+
});
|
196
|
+
|
197
|
+
// Copy the sorted breakpoint array into the breakpoints object using the
|
198
|
+
// name as the key.
|
199
|
+
this.breakpoints = {};
|
200
|
+
var i, l;
|
201
|
+
for (i = 0, l = breakpointsSorted.length; i < l; i++) {
|
202
|
+
this.breakpoints[breakpointsSorted[i].name] = breakpointsSorted[i];
|
203
|
+
}
|
204
|
+
|
205
|
+
/** Create range of visible columns and their indexes *****************/
|
206
|
+
// We need the range of all visible column indexes to calculate the
|
207
|
+
// columns to show:
|
208
|
+
// Columns to show = all visible columns - columns to hide
|
209
|
+
var columns = this.api.columns().header();
|
210
|
+
var visibleColumnsHeadersTds = [];
|
211
|
+
for (i = 0, l = columns.length; i < l; i++) {
|
212
|
+
if (this.api.columns(i).visible()) {
|
213
|
+
this.columnIndexes.push(i);
|
214
|
+
visibleColumnsHeadersTds.push(columns[i]);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
/** Sort columns into breakpoints respectively ************************/
|
219
|
+
// Read column headers' attributes and get needed info
|
220
|
+
for (var index = 0; index < visibleColumnsHeadersTds.length; index++) {
|
221
|
+
// Get the column with the attribute data-class="expand" so we know
|
222
|
+
// where to display the expand icon.
|
223
|
+
var col = $(visibleColumnsHeadersTds[index]);
|
224
|
+
|
225
|
+
if (col.attr('data-class') === 'expand') {
|
226
|
+
this.expandColumn = this.columnIndexes[index];
|
227
|
+
}
|
228
|
+
|
229
|
+
// The data-hide attribute has the breakpoints that this column
|
230
|
+
// is associated with.
|
231
|
+
// If it's defined, get the data-hide attribute and sort this
|
232
|
+
// column into the appropriate breakpoint's columnsToHide array.
|
233
|
+
var dataHide = col.attr('data-hide');
|
234
|
+
if (dataHide !== undefined) {
|
235
|
+
var splitBreakingPoints = dataHide.split(/,\s*/);
|
236
|
+
for (var i = 0; i < splitBreakingPoints.length; i++) {
|
237
|
+
var bp = splitBreakingPoints[i];
|
238
|
+
if (bp === 'always') {
|
239
|
+
// A column with an 'always' breakpoint is always hidden.
|
240
|
+
// Loop through all breakpoints and add it to each except the
|
241
|
+
// default breakpoint.
|
242
|
+
for (var prop in this.breakpoints) {
|
243
|
+
if (this.breakpoints[prop].name !== 'default') {
|
244
|
+
this.breakpoints[prop].columnsToHide.push(this.columnIndexes[index]);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
} else if (this.breakpoints[bp] !== undefined) {
|
248
|
+
// Translate visible column index to internal column index.
|
249
|
+
this.breakpoints[bp].columnsToHide.push(this.columnIndexes[index]);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
};
|
256
|
+
|
257
|
+
/**
|
258
|
+
* Sets or removes window resize handler.
|
259
|
+
*
|
260
|
+
* @param {Boolean} bindFlag
|
261
|
+
*/
|
262
|
+
ResponsiveDatatablesHelper.prototype.setWindowsResizeHandler = function(bindFlag) {
|
263
|
+
if (bindFlag === undefined) {
|
264
|
+
bindFlag = true;
|
265
|
+
}
|
266
|
+
|
267
|
+
if (bindFlag) {
|
268
|
+
var that = this;
|
269
|
+
$(window).bind("resize", function () {
|
270
|
+
that.respond();
|
271
|
+
});
|
272
|
+
} else {
|
273
|
+
$(window).unbind("resize");
|
274
|
+
}
|
275
|
+
};
|
276
|
+
|
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
|
+
|
358
|
+
/**
|
359
|
+
* Show/hide datatables columns.
|
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.
|
388
|
+
*
|
389
|
+
* @param {Object} tr table row object
|
390
|
+
*/
|
391
|
+
ResponsiveDatatablesHelper.prototype.createExpandIcon = function (tr) {
|
392
|
+
if (this.disabled) {
|
393
|
+
return;
|
394
|
+
}
|
395
|
+
|
396
|
+
// Get the td for tr with the same index as the th in the header tr
|
397
|
+
// that has the data-class="expand" attribute defined.
|
398
|
+
var tds = $('td', tr);
|
399
|
+
// Loop through tds and create an expand icon on the td that has a column
|
400
|
+
// index equal to the expand column given.
|
401
|
+
for (var i = 0, l = tds.length; i < l; i++) {
|
402
|
+
var td = tds[i];
|
403
|
+
var tdIndex = this.api.cell(td).index().column;
|
404
|
+
td = $(td);
|
405
|
+
if (tdIndex === this.expandColumn) {
|
406
|
+
// Create expand icon if there isn't one already.
|
407
|
+
if ($('span.responsiveExpander', td).length == 0) {
|
408
|
+
td.prepend(this.expandIconTemplate);
|
409
|
+
|
410
|
+
// Respond to click event on expander icon.
|
411
|
+
switch (this.options.clickOn) {
|
412
|
+
case 'cell':
|
413
|
+
td.on('click', {responsiveDatatablesHelperInstance: this}, this.showRowDetailEventHandler);
|
414
|
+
break;
|
415
|
+
case 'row':
|
416
|
+
$(tr).on('click', {responsiveDatatablesHelperInstance: this}, this.showRowDetailEventHandler);
|
417
|
+
break;
|
418
|
+
default:
|
419
|
+
td.on('click', 'span.responsiveExpander', {responsiveDatatablesHelperInstance: this}, this.showRowDetailEventHandler);
|
420
|
+
break;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
break;
|
424
|
+
}
|
425
|
+
}
|
426
|
+
};
|
427
|
+
|
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
|
+
|
442
|
+
var td = $(this);
|
443
|
+
|
444
|
+
// Nothing to do if there are no columns hidden.
|
445
|
+
if (!td.closest('table').hasClass('has-columns-hidden')) {
|
446
|
+
return;
|
447
|
+
}
|
448
|
+
|
449
|
+
// Get the parent tr of which this td belongs to.
|
450
|
+
var tr = td.closest('tr');
|
451
|
+
|
452
|
+
// Show/hide row details
|
453
|
+
if (tr.hasClass('detail-show')) {
|
454
|
+
ResponsiveDatatablesHelper.prototype.hideRowDetail(responsiveDatatablesHelperInstance, tr);
|
455
|
+
} else {
|
456
|
+
ResponsiveDatatablesHelper.prototype.showRowDetail(responsiveDatatablesHelperInstance, tr);
|
457
|
+
}
|
458
|
+
|
459
|
+
tr.toggleClass('detail-show');
|
460
|
+
|
461
|
+
// Prevent click event from bubbling up to higher-level DOM elements.
|
462
|
+
event.stopPropagation();
|
463
|
+
};
|
464
|
+
|
465
|
+
/**
|
466
|
+
* Show row details.
|
467
|
+
*
|
468
|
+
* @param {ResponsiveDatatablesHelper} responsiveDatatablesHelperInstance instance of ResponsiveDatatablesHelper
|
469
|
+
* @param {Object} tr jQuery wrapped set
|
470
|
+
*/
|
471
|
+
ResponsiveDatatablesHelper.prototype.showRowDetail = function (responsiveDatatablesHelperInstance, tr) {
|
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
|
+
};
|
534
|
+
|
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
|
+
|
565
|
+
if (this.disabled) {
|
566
|
+
// Remove windows resize handler.
|
567
|
+
this.setWindowsResizeHandler(false);
|
568
|
+
|
569
|
+
// Remove all trs that have row details.
|
570
|
+
$('tbody tr.row-detail', this.tableElement).remove();
|
571
|
+
|
572
|
+
// Remove all trs that are marked to have row details shown.
|
573
|
+
$('tbody tr', this.tableElement).removeClass('detail-show');
|
574
|
+
|
575
|
+
// Remove all expander icons.
|
576
|
+
$('tbody tr span.responsiveExpander', this.tableElement).remove();
|
577
|
+
|
578
|
+
this.columnsHiddenIndexes = [];
|
579
|
+
this.columnsShownIndexes = this.columnIndexes;
|
580
|
+
this.showHideColumns();
|
581
|
+
this.tableElement.removeClass('has-columns-hidden');
|
582
|
+
|
583
|
+
this.tableElement.off('click', 'span.responsiveExpander', this.showRowDetailEventHandler);
|
584
|
+
} else {
|
585
|
+
// Add windows resize handler.
|
586
|
+
this.setWindowsResizeHandler();
|
587
|
+
}
|
588
|
+
};
|
589
|
+
|
590
|
+
/**
|
591
|
+
* Get state from cookie.
|
592
|
+
*/
|
593
|
+
ResponsiveDatatablesHelper.prototype.getState = function () {
|
594
|
+
try {
|
595
|
+
var value = JSON.parse(decodeURIComponent(this.getCookie(this.cookieName)));
|
596
|
+
if (value) {
|
597
|
+
this.columnIndexes = value.columnIndexes;
|
598
|
+
this.breakpoints = value.breakpoints;
|
599
|
+
this.expandColumn = value.expandColumn;
|
600
|
+
this.lastBreakpoint = value.lastBreakpoint;
|
601
|
+
this.lastStateExists = true;
|
602
|
+
}
|
603
|
+
} catch (e) {
|
604
|
+
}
|
605
|
+
};
|
606
|
+
|
607
|
+
/**
|
608
|
+
* Saves state to cookie.
|
609
|
+
*/
|
610
|
+
ResponsiveDatatablesHelper.prototype.setState = function () {
|
611
|
+
var d1 = this.difference(this.lastColumnsHiddenIndexes, this.columnsHiddenIndexes).length;
|
612
|
+
var d2 = this.difference(this.columnsHiddenIndexes, this.lastColumnsHiddenIndexes).length;
|
613
|
+
|
614
|
+
if (d1 + d2 > 0) {
|
615
|
+
var value = encodeURIComponent(JSON.stringify({
|
616
|
+
columnIndexes: this.columnIndexes,
|
617
|
+
columnsHiddenIndexes: this.columnsHiddenIndexes,
|
618
|
+
breakpoints: this.breakpoints,
|
619
|
+
expandColumn: this.expandColumn,
|
620
|
+
lastBreakpoint: this.lastBreakpoint
|
621
|
+
}));
|
622
|
+
|
623
|
+
this.setCookie(this.cookieName, value, 2 * 60 * 60 * 1000);
|
624
|
+
this.lastColumnsHiddenIndexes = this.columnsHiddenIndexes.slice(0);
|
625
|
+
}
|
626
|
+
};
|
627
|
+
|
628
|
+
/**
|
629
|
+
* Get cookie.
|
630
|
+
*/
|
631
|
+
ResponsiveDatatablesHelper.prototype.getCookie = function (cname) {
|
632
|
+
var name = cname + "=";
|
633
|
+
var ca = document.cookie.split(';');
|
634
|
+
for (var i = 0; i < ca.length; i++) {
|
635
|
+
var c = ca[i].trim();
|
636
|
+
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
|
637
|
+
}
|
638
|
+
return "";
|
639
|
+
};
|
640
|
+
|
641
|
+
/**
|
642
|
+
* Set cookie.
|
643
|
+
*/
|
644
|
+
ResponsiveDatatablesHelper.prototype.setCookie = function (cname, cvalue, cexp) {
|
645
|
+
var d = new Date();
|
646
|
+
d.setTime(d.getTime() + cexp);
|
647
|
+
var expires = "expires=" + d.toGMTString();
|
648
|
+
document.cookie = cname + "=" + cvalue + "; " + expires;
|
649
|
+
};
|
650
|
+
|
651
|
+
/**
|
652
|
+
* Get Difference.
|
653
|
+
*/
|
654
|
+
ResponsiveDatatablesHelper.prototype.difference = function (a, b) {
|
655
|
+
var arr = [], i, hash = {};
|
656
|
+
for (i = b.length - 1; i >= 0; i--) {
|
657
|
+
hash[b[i]] = true;
|
658
|
+
}
|
659
|
+
for (i = a.length - 1; i >= 0; i--) {
|
660
|
+
if (hash[a[i]] !== true) {
|
661
|
+
arr.push(a[i]);
|
662
|
+
}
|
663
|
+
}
|
664
|
+
return arr;
|
665
|
+
};
|
File without changes
|
File without changes
|
@@ -15,6 +15,7 @@ table.has-columns-hidden > tbody > tr.row-detail > td {
|
|
15
15
|
table.has-columns-hidden > tbody > tr.row-detail > td > ul {
|
16
16
|
list-style: none;
|
17
17
|
margin: 0;
|
18
|
+
padding: 0;
|
18
19
|
}
|
19
20
|
|
20
21
|
table.has-columns-hidden > tbody > tr.row-detail > td > ul > li > span.columnTitle {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jquery-datatables-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.10.0.
|
4
|
+
version: 2.1.10.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Wenglewski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jquery-rails
|
@@ -81,6 +81,8 @@ files:
|
|
81
81
|
- app/assets/images/dataTables/sort_both.png
|
82
82
|
- app/assets/images/dataTables/sort_desc.png
|
83
83
|
- app/assets/images/dataTables/sort_desc_disabled.png
|
84
|
+
- app/assets/javascripts/dataTables/bootstrap/2/jquery.dataTables.bootstrap.js
|
85
|
+
- app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js
|
84
86
|
- app/assets/javascripts/dataTables/extras/ZeroClipboard.js
|
85
87
|
- app/assets/javascripts/dataTables/extras/dataTables.autoFill.js
|
86
88
|
- app/assets/javascripts/dataTables/extras/dataTables.colReorder.js
|
@@ -88,17 +90,15 @@ files:
|
|
88
90
|
- app/assets/javascripts/dataTables/extras/dataTables.fixedColumns.js
|
89
91
|
- app/assets/javascripts/dataTables/extras/dataTables.fixedHeader.js
|
90
92
|
- app/assets/javascripts/dataTables/extras/dataTables.keyTable.js
|
93
|
+
- app/assets/javascripts/dataTables/extras/dataTables.responsive.js
|
91
94
|
- app/assets/javascripts/dataTables/extras/dataTables.scroller.js
|
92
95
|
- app/assets/javascripts/dataTables/extras/dataTables.tableTools.js
|
93
96
|
- app/assets/javascripts/dataTables/jquery.dataTables.api.fnFilterOnReturn.js
|
94
97
|
- app/assets/javascripts/dataTables/jquery.dataTables.api.fnGetColumnData.js
|
95
98
|
- app/assets/javascripts/dataTables/jquery.dataTables.api.fnReloadAjax.js
|
96
99
|
- app/assets/javascripts/dataTables/jquery.dataTables.api.fnSetFilteringDelay.js
|
97
|
-
- app/assets/javascripts/dataTables/jquery.dataTables.bootstrap.js
|
98
|
-
- app/assets/javascripts/dataTables/jquery.dataTables.bootstrap3.js
|
99
100
|
- app/assets/javascripts/dataTables/jquery.dataTables.foundation.js
|
100
101
|
- app/assets/javascripts/dataTables/jquery.dataTables.js
|
101
|
-
- app/assets/javascripts/dataTables/jquery.dataTables.responsive.js
|
102
102
|
- app/assets/javascripts/dataTables/jquery.dataTables.sorting.numbersHtml.js
|
103
103
|
- app/assets/javascripts/dataTables/jquery.dataTables.typeDetection.numbersHtml.js
|
104
104
|
- app/assets/media/dataTables/extras/as3/ZeroClipboard.as
|
@@ -106,6 +106,8 @@ files:
|
|
106
106
|
- app/assets/media/dataTables/extras/as3/lib/AlivePDF.swc
|
107
107
|
- app/assets/media/dataTables/extras/swf/copy_csv_xls.swf
|
108
108
|
- app/assets/media/dataTables/extras/swf/copy_csv_xls_pdf.swf
|
109
|
+
- app/assets/stylesheets/dataTables/bootstrap/2/jquery.dataTables.bootstrap.css.scss
|
110
|
+
- app/assets/stylesheets/dataTables/bootstrap/3/jquery.dataTables.bootstrap.css.scss
|
109
111
|
- app/assets/stylesheets/dataTables/extras/TableTools_JUI.css
|
110
112
|
- app/assets/stylesheets/dataTables/extras/dataTables.autoFill.css.scss
|
111
113
|
- app/assets/stylesheets/dataTables/extras/dataTables.colReorder.css.scss
|
@@ -114,13 +116,11 @@ files:
|
|
114
116
|
- app/assets/stylesheets/dataTables/extras/dataTables.fixedColumns.css.scss
|
115
117
|
- app/assets/stylesheets/dataTables/extras/dataTables.fixedHeader.css.scss
|
116
118
|
- app/assets/stylesheets/dataTables/extras/dataTables.keyTable.css.scss
|
119
|
+
- app/assets/stylesheets/dataTables/extras/dataTables.responsive.css.scss
|
117
120
|
- app/assets/stylesheets/dataTables/extras/dataTables.scroller.css.scss
|
118
121
|
- app/assets/stylesheets/dataTables/extras/dataTables.tableTools.css.scss
|
119
|
-
- app/assets/stylesheets/dataTables/jquery.dataTables.bootstrap.css.scss
|
120
|
-
- app/assets/stylesheets/dataTables/jquery.dataTables.bootstrap3.css.scss
|
121
122
|
- app/assets/stylesheets/dataTables/jquery.dataTables.css.scss
|
122
123
|
- app/assets/stylesheets/dataTables/jquery.dataTables.foundation.css.scss
|
123
|
-
- app/assets/stylesheets/dataTables/jquery.dataTables.responsive.css.scss
|
124
124
|
- app/assets/stylesheets/dataTables/src/demo_page.css
|
125
125
|
- app/assets/stylesheets/dataTables/src/demo_table.css
|
126
126
|
- app/assets/stylesheets/dataTables/src/demo_table_jui.css
|
@@ -152,3 +152,4 @@ signing_key:
|
|
152
152
|
specification_version: 4
|
153
153
|
summary: jquery datatables for rails
|
154
154
|
test_files: []
|
155
|
+
has_rdoc:
|
@@ -1,435 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* File: datatables.responsive.js
|
3
|
-
* Version: 0.1.2
|
4
|
-
* Author: Seen Sai Yang
|
5
|
-
* Info: https://github.com/Comanche/datatables-responsive
|
6
|
-
*
|
7
|
-
* Copyright 2013 Seen Sai Yang, all rights reserved.
|
8
|
-
*
|
9
|
-
* This source file is free software, under either the GPL v2 license or a
|
10
|
-
* BSD style license.
|
11
|
-
*
|
12
|
-
* This source file is distributed in the hope that it will be useful, but
|
13
|
-
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
14
|
-
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
15
|
-
*
|
16
|
-
* You should have received a copy of the GNU General Public License and the
|
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
|
20
|
-
*/
|
21
|
-
|
22
|
-
'use strict';
|
23
|
-
|
24
|
-
/**
|
25
|
-
* Constructor for responsive datables helper.
|
26
|
-
*
|
27
|
-
* This helper class makes datatables responsive to the window size.
|
28
|
-
*
|
29
|
-
* The parameter, breakpoints, is an object for each breakpoint key/value pair
|
30
|
-
* with the following format: { breakpoint_name: pixel_width_at_breakpoint }.
|
31
|
-
*
|
32
|
-
* An example is as follows:
|
33
|
-
*
|
34
|
-
* {
|
35
|
-
* tablet: 1024,
|
36
|
-
* phone: 480
|
37
|
-
* }
|
38
|
-
*
|
39
|
-
* These breakpoint name may be used as possible values for the data-hide
|
40
|
-
* attribute. The data-hide attribute is optional and may be defined for each
|
41
|
-
* th element in the table header.
|
42
|
-
*
|
43
|
-
* @param {Object|string} tableSelector jQuery wrapped set or selector for
|
44
|
-
* datatables container element.
|
45
|
-
* @param {Object} breakpoints Object defining the responsive
|
46
|
-
* breakpoint for datatables.
|
47
|
-
*/
|
48
|
-
function ResponsiveDatatablesHelper(tableSelector, breakpoints) {
|
49
|
-
if (typeof tableSelector === 'string') {
|
50
|
-
this.tableElement = $(tableSelector);
|
51
|
-
} else {
|
52
|
-
this.tableElement = tableSelector;
|
53
|
-
}
|
54
|
-
|
55
|
-
// State of column indexes and which are shown or hidden.
|
56
|
-
this.columnIndexes = [];
|
57
|
-
this.columnsShownIndexes = [];
|
58
|
-
this.columnsHiddenIndexes = [];
|
59
|
-
|
60
|
-
// Index of the th in the header tr that stores where the attribute
|
61
|
-
// data-class="expand"
|
62
|
-
// is defined.
|
63
|
-
this.expandColumn = undefined;
|
64
|
-
|
65
|
-
// Stores the break points defined in the table header.
|
66
|
-
// Each th in the header tr may contain an optional attribute like
|
67
|
-
// data-hide="phone,tablet"
|
68
|
-
// These attributes and the breakpoints object will be used to create this
|
69
|
-
// object.
|
70
|
-
this.breakpoints = {
|
71
|
-
/**
|
72
|
-
* We will be generating data in the following format:
|
73
|
-
* phone : {
|
74
|
-
* lowerLimit : undefined,
|
75
|
-
* upperLimit : 320,
|
76
|
-
* columnsToHide: []
|
77
|
-
* },
|
78
|
-
* tablet: {
|
79
|
-
* lowerLimit : 320,
|
80
|
-
* upperLimit : 724,
|
81
|
-
* columnsToHide: []
|
82
|
-
* }
|
83
|
-
*/
|
84
|
-
};
|
85
|
-
|
86
|
-
// Expand icon template
|
87
|
-
this.expandIconTemplate = '<span class="responsiveExpander"></span>';
|
88
|
-
|
89
|
-
// Row template
|
90
|
-
this.rowTemplate = '<tr class="row-detail"><td><ul><!--column item--></ul></td></tr>';
|
91
|
-
this.rowLiTemplate = '<li><span class="columnTitle"><!--column title--></span>: <!--column value--></li>';
|
92
|
-
|
93
|
-
// Responsive behavior on/off flag
|
94
|
-
this.disabled = true;
|
95
|
-
|
96
|
-
// Skip next windows width change flag
|
97
|
-
this.skipNextWindowsWidthChange = false;
|
98
|
-
|
99
|
-
// Initialize settings
|
100
|
-
this.init(breakpoints);
|
101
|
-
}
|
102
|
-
|
103
|
-
/**
|
104
|
-
* Responsive datatables helper init function. Builds breakpoint limits
|
105
|
-
* for columns and begins to listen to window resize event.
|
106
|
-
*
|
107
|
-
* See constructor for the breakpoints parameter.
|
108
|
-
*
|
109
|
-
* @param {Object} breakpoints
|
110
|
-
*/
|
111
|
-
ResponsiveDatatablesHelper.prototype.init = function (breakpoints) {
|
112
|
-
/** Generate breakpoints in the format we need. ***************************/
|
113
|
-
// First, we need to create a sorted array of the breakpoints given.
|
114
|
-
var breakpointsSorted = [];
|
115
|
-
_.each(breakpoints, function (value, key) {
|
116
|
-
breakpointsSorted.push({
|
117
|
-
name : key,
|
118
|
-
upperLimit : value,
|
119
|
-
columnsToHide: []
|
120
|
-
});
|
121
|
-
});
|
122
|
-
breakpointsSorted = _.sortBy(breakpointsSorted, 'upperLimit');
|
123
|
-
|
124
|
-
// Set lower and upper limits for each breakpoint.
|
125
|
-
var lowerLimit = undefined;
|
126
|
-
_.each(breakpointsSorted, function (value) {
|
127
|
-
value.lowerLimit = lowerLimit;
|
128
|
-
lowerLimit = value.upperLimit;
|
129
|
-
});
|
130
|
-
|
131
|
-
// Add the default breakpoint which shows all (has no upper limit).
|
132
|
-
breakpointsSorted.push({
|
133
|
-
name : 'default',
|
134
|
-
lowerLimit : lowerLimit,
|
135
|
-
upperLimit : undefined,
|
136
|
-
columnsToHide: []
|
137
|
-
});
|
138
|
-
|
139
|
-
// Copy the sorted breakpoint array into the breakpoints object using the
|
140
|
-
// name as the key.
|
141
|
-
for (var i = 0, l = breakpointsSorted.length; i < l; i++) {
|
142
|
-
this.breakpoints[breakpointsSorted[i].name] = breakpointsSorted[i];
|
143
|
-
}
|
144
|
-
|
145
|
-
/** Create range of possible column indexes *******************************/
|
146
|
-
// Get all visible column indexes
|
147
|
-
var columns = this.tableElement.fnSettings().aoColumns;
|
148
|
-
for (var i = 0, l = columns.length; i < l; i++) {
|
149
|
-
if (columns[i].bVisible) {
|
150
|
-
this.columnIndexes.push(i)
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
// We need the range of possible column indexes to calculate the columns
|
155
|
-
// to show:
|
156
|
-
// Columns to show = all columns - columns to hide
|
157
|
-
var headerElements = $('thead th', this.tableElement);
|
158
|
-
|
159
|
-
/** Add columns into breakpoints respectively *****************************/
|
160
|
-
// Read column headers' attributes and get needed info
|
161
|
-
_.each(headerElements, function (element, index) {
|
162
|
-
// Get the column with the attribute data-class="expand" so we know
|
163
|
-
// where to display the expand icon.
|
164
|
-
if ($(element).attr('data-class') === 'expand') {
|
165
|
-
this.expandColumn = index;
|
166
|
-
}
|
167
|
-
|
168
|
-
// The data-hide attribute has the breakpoints that this column
|
169
|
-
// is associated with.
|
170
|
-
// If it's defined, get the data-hide attribute and sort this
|
171
|
-
// column into the appropriate breakpoint's columnsToHide array.
|
172
|
-
var dataHide = $(element).attr('data-hide');
|
173
|
-
if (dataHide !== undefined) {
|
174
|
-
var splitBreakingPoints = dataHide.split(/,\s*/);
|
175
|
-
_.each(splitBreakingPoints, function (e) {
|
176
|
-
if (this.breakpoints[e] !== undefined) {
|
177
|
-
// Translate visible column index to internal column index.
|
178
|
-
this.breakpoints[e].columnsToHide.push(this.columnIndexes[index]);
|
179
|
-
}
|
180
|
-
}, this);
|
181
|
-
}
|
182
|
-
}, this);
|
183
|
-
|
184
|
-
// Enable responsive behavior.
|
185
|
-
this.disable(false);
|
186
|
-
};
|
187
|
-
|
188
|
-
ResponsiveDatatablesHelper.prototype.setWindowsResizeHandler = function(bindFlag) {
|
189
|
-
if (bindFlag === undefined) {
|
190
|
-
bindFlag = true;
|
191
|
-
}
|
192
|
-
|
193
|
-
if (bindFlag) {
|
194
|
-
var that = this;
|
195
|
-
$(window).bind("resize", function () {
|
196
|
-
that.respond();
|
197
|
-
});
|
198
|
-
} else {
|
199
|
-
$(window).unbind("resize");
|
200
|
-
}
|
201
|
-
}
|
202
|
-
|
203
|
-
/**
|
204
|
-
* Respond window size change. This helps make datatables responsive.
|
205
|
-
*/
|
206
|
-
ResponsiveDatatablesHelper.prototype.respond = function () {
|
207
|
-
if (this.disabled) {
|
208
|
-
return;
|
209
|
-
}
|
210
|
-
|
211
|
-
// Get new windows width
|
212
|
-
var newWindowWidth = $(window).width();
|
213
|
-
var updatedHiddenColumnsCount = 0;
|
214
|
-
|
215
|
-
// Loop through breakpoints to see which columns need to be shown/hidden.
|
216
|
-
var newColumnsToHide = [];
|
217
|
-
_.each(this.breakpoints, function (element) {
|
218
|
-
if ((!element.lowerLimit || newWindowWidth > element.lowerLimit) && (!element.upperLimit || newWindowWidth <= element.upperLimit)) {
|
219
|
-
newColumnsToHide = element.columnsToHide;
|
220
|
-
}
|
221
|
-
}, this);
|
222
|
-
|
223
|
-
// Find out if a column show/hide should happen.
|
224
|
-
// Skip column show/hide if this window width change follows immediately
|
225
|
-
// after a previous column show/hide. This will help prevent a loop.
|
226
|
-
var columnShowHide = false;
|
227
|
-
if (!this.skipNextWindowsWidthChange) {
|
228
|
-
// Check difference in length
|
229
|
-
if (this.columnsHiddenIndexes.length !== newColumnsToHide.length) {
|
230
|
-
// Difference in length
|
231
|
-
columnShowHide = true;
|
232
|
-
} else {
|
233
|
-
// Same length but check difference in values
|
234
|
-
var d1 = _.difference(this.columnsHiddenIndexes, newColumnsToHide).length;
|
235
|
-
var d2 = _.difference(newColumnsToHide, this.columnsHiddenIndexes).length;
|
236
|
-
columnShowHide = d1 + d2 > 0;
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
if (columnShowHide) {
|
241
|
-
// Showing/hiding a column at breakpoint may cause a windows width
|
242
|
-
// change. Let's flag to skip the column show/hide that may be
|
243
|
-
// caused by the next windows width change.
|
244
|
-
this.skipNextWindowsWidthChange = true;
|
245
|
-
this.columnsHiddenIndexes = newColumnsToHide;
|
246
|
-
this.columnsShownIndexes = _.difference(this.columnIndexes, this.columnsHiddenIndexes);
|
247
|
-
this.showHideColumns();
|
248
|
-
updatedHiddenColumnsCount = this.columnsHiddenIndexes.length;
|
249
|
-
this.skipNextWindowsWidthChange = false;
|
250
|
-
}
|
251
|
-
|
252
|
-
|
253
|
-
// We don't skip this part.
|
254
|
-
// If one or more columns have been hidden, add the has-columns-hidden class to table.
|
255
|
-
// This class will show what state the table is in.
|
256
|
-
if (this.columnsHiddenIndexes.length) {
|
257
|
-
this.tableElement.addClass('has-columns-hidden');
|
258
|
-
var that = this;
|
259
|
-
|
260
|
-
// Show details for each row that is tagged with the class .detail-show.
|
261
|
-
$('tr.detail-show', this.tableElement).each(function (index, element) {
|
262
|
-
var tr = $(element);
|
263
|
-
if (tr.next('.row-detail').length === 0) {
|
264
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(that, tr);
|
265
|
-
}
|
266
|
-
});
|
267
|
-
} else {
|
268
|
-
this.tableElement.removeClass('has-columns-hidden');
|
269
|
-
$('tr.row-detail').remove();
|
270
|
-
}
|
271
|
-
};
|
272
|
-
|
273
|
-
/**
|
274
|
-
* Show/hide datatables columns.
|
275
|
-
*/
|
276
|
-
ResponsiveDatatablesHelper.prototype.showHideColumns = function () {
|
277
|
-
// Calculate the columns to show
|
278
|
-
// Show columns that may have been previously hidden.
|
279
|
-
for (var i = 0, l = this.columnsShownIndexes.length; i < l; i++) {
|
280
|
-
this.tableElement.fnSetColumnVis(this.columnsShownIndexes[i], true, false);
|
281
|
-
}
|
282
|
-
|
283
|
-
// Hide columns that may have been previously shown.
|
284
|
-
for (var i = 0, l = this.columnsHiddenIndexes.length; i < l; i++) {
|
285
|
-
this.tableElement.fnSetColumnVis(this.columnsHiddenIndexes[i], false, false);
|
286
|
-
}
|
287
|
-
|
288
|
-
// Rebuild details to reflect shown/hidden column changes.
|
289
|
-
var that = this;
|
290
|
-
$('tr.row-detail').remove();
|
291
|
-
if (this.tableElement.hasClass('has-columns-hidden')) {
|
292
|
-
$('tr.detail-show', this.tableElement).each(function (index, element) {
|
293
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(that, $(element));
|
294
|
-
});
|
295
|
-
}
|
296
|
-
};
|
297
|
-
|
298
|
-
/**
|
299
|
-
* Create the expand icon on the column with the data-class="expand" attribute
|
300
|
-
* defined for it's header.
|
301
|
-
*
|
302
|
-
* @param {Object} tr table row object
|
303
|
-
*/
|
304
|
-
ResponsiveDatatablesHelper.prototype.createExpandIcon = function (tr) {
|
305
|
-
if (this.disabled) {
|
306
|
-
return;
|
307
|
-
}
|
308
|
-
|
309
|
-
// Get the td for tr with the same index as the th in the header tr
|
310
|
-
// that has the data-class="expand" attribute defined.
|
311
|
-
var tds = $('td', tr);
|
312
|
-
var that = this;
|
313
|
-
// Loop through tds and create an expand icon on the td that has a column
|
314
|
-
// index equal to the expand column given.
|
315
|
-
for (var i = 0, l = tds.length; i < l; i++) {
|
316
|
-
var td = tds[i];
|
317
|
-
var tdIndex = that.tableElement.fnGetPosition(td)[2];
|
318
|
-
td = $(td);
|
319
|
-
if (tdIndex === that.expandColumn) {
|
320
|
-
// Create expand icon if there isn't one already.
|
321
|
-
if ($('span.responsiveExpander', td).length == 0) {
|
322
|
-
td.prepend(that.expandIconTemplate);
|
323
|
-
|
324
|
-
// Respond to click event on expander icon.
|
325
|
-
td.on('click', 'span.responsiveExpander', {responsiveDatatablesHelperInstance: that}, that.showRowDetailEventHandler);
|
326
|
-
}
|
327
|
-
break;
|
328
|
-
}
|
329
|
-
}
|
330
|
-
};
|
331
|
-
|
332
|
-
/**
|
333
|
-
* Show row detail event handler.
|
334
|
-
*
|
335
|
-
* This handler is used to handle the click event of the expand icon defined in
|
336
|
-
* the table row data element.
|
337
|
-
*
|
338
|
-
* @param {Object} event jQuery event object
|
339
|
-
*/
|
340
|
-
ResponsiveDatatablesHelper.prototype.showRowDetailEventHandler = function (event) {
|
341
|
-
if (this.disabled) {
|
342
|
-
return;
|
343
|
-
}
|
344
|
-
|
345
|
-
// Get the parent tr of which this td belongs to.
|
346
|
-
var tr = $(this).closest('tr');
|
347
|
-
|
348
|
-
// Show/hide row details
|
349
|
-
if (tr.hasClass('detail-show')) {
|
350
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail(event.data.responsiveDatatablesHelperInstance, tr);
|
351
|
-
} else {
|
352
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail(event.data.responsiveDatatablesHelperInstance, tr);
|
353
|
-
}
|
354
|
-
|
355
|
-
tr.toggleClass('detail-show');
|
356
|
-
|
357
|
-
// Prevent click event from bubbling up to higher-level DOM elements.
|
358
|
-
event.stopPropagation();
|
359
|
-
};
|
360
|
-
|
361
|
-
/**
|
362
|
-
* Show row details
|
363
|
-
*
|
364
|
-
* @param {ResponsiveDatatablesHelper} responsiveDatatablesHelperInstance instance of ResponsiveDatatablesHelper
|
365
|
-
* @param {Object} tr jQuery wrapped set
|
366
|
-
*/
|
367
|
-
ResponsiveDatatablesHelper.prototype.showRowDetail = function (responsiveDatatablesHelperInstance, tr) {
|
368
|
-
// Get column because we need their titles.
|
369
|
-
var tableContainer = responsiveDatatablesHelperInstance.tableElement;
|
370
|
-
var columns = tableContainer.fnSettings().aoColumns;
|
371
|
-
|
372
|
-
// Create the new tr.
|
373
|
-
var newTr = $(responsiveDatatablesHelperInstance.rowTemplate);
|
374
|
-
|
375
|
-
// Get the ul that we'll insert li's into.
|
376
|
-
var ul = $('ul', newTr);
|
377
|
-
|
378
|
-
// Loop through hidden columns and create an li for each of them.
|
379
|
-
_.each(responsiveDatatablesHelperInstance.columnsHiddenIndexes, function (index) {
|
380
|
-
var li = $(responsiveDatatablesHelperInstance.rowLiTemplate);
|
381
|
-
$('.columnTitle', li).html(columns[index].sTitle);
|
382
|
-
li.append(tableContainer.fnGetData(tr[0], index));
|
383
|
-
ul.append(li);
|
384
|
-
});
|
385
|
-
|
386
|
-
// Create tr colspan attribute
|
387
|
-
var colspan = responsiveDatatablesHelperInstance.columnIndexes.length - responsiveDatatablesHelperInstance.columnsHiddenIndexes.length;
|
388
|
-
$('td', newTr).attr('colspan', colspan);
|
389
|
-
|
390
|
-
// Append the new tr after the current tr.
|
391
|
-
tr.after(newTr);
|
392
|
-
};
|
393
|
-
|
394
|
-
/**
|
395
|
-
* Hide row details
|
396
|
-
*
|
397
|
-
* @param {ResponsiveDatatablesHelper} responsiveDatatablesHelperInstance instance of ResponsiveDatatablesHelper
|
398
|
-
* @param {Object} tr jQuery wrapped set
|
399
|
-
*/
|
400
|
-
ResponsiveDatatablesHelper.prototype.hideRowDetail = function (responsiveDatatablesHelperInstance, tr) {
|
401
|
-
tr.next('.row-detail').remove();
|
402
|
-
};
|
403
|
-
|
404
|
-
/**
|
405
|
-
* Enable/disable responsive behavior and restores changes made.
|
406
|
-
*
|
407
|
-
* @param {Boolean} disable, default is true
|
408
|
-
*/
|
409
|
-
ResponsiveDatatablesHelper.prototype.disable = function (disable) {
|
410
|
-
this.disabled = (disable === undefined) || disable;
|
411
|
-
|
412
|
-
if (this.disabled) {
|
413
|
-
// Remove windows resize handler
|
414
|
-
this.setWindowsResizeHandler(false);
|
415
|
-
|
416
|
-
// Remove all trs that have row details.
|
417
|
-
$('tbody tr.row-detail', this.tableElement).remove();
|
418
|
-
|
419
|
-
// Remove all trs that are marked to have row details shown.
|
420
|
-
$('tbody tr', this.tableElement).removeClass('detail-show');
|
421
|
-
|
422
|
-
// Remove all expander icons
|
423
|
-
$('tbody tr span.responsiveExpander', this.tableElement).remove();
|
424
|
-
|
425
|
-
this.columnsHiddenIndexes = [];
|
426
|
-
this.columnsShownIndexes = this.columnIndexes;
|
427
|
-
this.showHideColumns();
|
428
|
-
this.tableElement.removeClass('has-columns-hidden');
|
429
|
-
|
430
|
-
this.tableElement.off('click', 'span.responsiveExpander', this.showRowDetailEventHandler);
|
431
|
-
} else {
|
432
|
-
// Add windows resize handler
|
433
|
-
this.setWindowsResizeHandler();
|
434
|
-
}
|
435
|
-
}
|