jquery-datatables-rails 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/dataTables/bootstrap/3/jquery.dataTables.bootstrap.js +64 -29
  3. data/app/assets/javascripts/dataTables/extras/dataTables.autoFill.js +806 -648
  4. data/app/assets/javascripts/dataTables/extras/dataTables.buttons.js +1607 -0
  5. data/app/assets/javascripts/dataTables/extras/dataTables.colReorder.js +220 -267
  6. data/app/assets/javascripts/dataTables/extras/dataTables.fixedColumns.js +164 -69
  7. data/app/assets/javascripts/dataTables/extras/dataTables.fixedHeader.js +469 -870
  8. data/app/assets/javascripts/dataTables/extras/dataTables.keyTable.js +636 -972
  9. data/app/assets/javascripts/dataTables/extras/dataTables.responsive.js +472 -187
  10. data/app/assets/javascripts/dataTables/extras/dataTables.rowReorder.js +619 -0
  11. data/app/assets/javascripts/dataTables/extras/dataTables.scroller.js +146 -111
  12. data/app/assets/javascripts/dataTables/extras/dataTables.select.js +1038 -0
  13. data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnGetColumnData.js +0 -0
  14. data/app/assets/javascripts/dataTables/jquery.dataTables.api.fnReloadAjax.js +0 -0
  15. data/app/assets/javascripts/dataTables/jquery.dataTables.foundation.js +37 -61
  16. data/app/assets/javascripts/dataTables/jquery.dataTables.js +720 -387
  17. data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.ipAddress.js +44 -0
  18. data/app/assets/javascripts/dataTables/jquery.dataTables.sorting.numbersHtml.js +0 -0
  19. data/app/assets/javascripts/dataTables/jquery.dataTables.typeDetection.numbersHtml.js +0 -0
  20. data/app/assets/stylesheets/dataTables/jquery.dataTables.scss +34 -66
  21. data/app/assets/stylesheets/dataTables/src/demo_table.css +1 -1
  22. data/app/assets/stylesheets/dataTables/src/demo_table_jui.css.scss +4 -4
  23. data/lib/jquery/datatables/rails/version.rb +1 -1
  24. metadata +24 -19
@@ -1,11 +1,11 @@
1
- /*! Responsive 1.0.5
1
+ /*! Responsive 2.0.0
2
2
  * 2014-2015 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  /**
6
6
  * @summary Responsive
7
7
  * @description Responsive tables plug-in for DataTables
8
- * @version 1.0.5
8
+ * @version 2.0.0
9
9
  * @file dataTables.responsive.js
10
10
  * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
11
  * @contact www.sprymedia.co.uk/contact
@@ -20,12 +20,35 @@
20
20
  *
21
21
  * For details please refer to: http://www.datatables.net
22
22
  */
23
+ (function( factory ){
24
+ if ( typeof define === 'function' && define.amd ) {
25
+ // AMD
26
+ define( ['jquery', 'datatables.net'], function ( $ ) {
27
+ return factory( $, window, document );
28
+ } );
29
+ }
30
+ else if ( typeof exports === 'object' ) {
31
+ // CommonJS
32
+ module.exports = function (root, $) {
33
+ if ( ! root ) {
34
+ root = window;
35
+ }
23
36
 
24
- (function(window, document, undefined) {
37
+ if ( ! $ || ! $.fn.dataTable ) {
38
+ $ = require('datatables.net')(root, $).$;
39
+ }
25
40
 
41
+ return factory( $, root, root.document );
42
+ };
43
+ }
44
+ else {
45
+ // Browser
46
+ factory( jQuery, window, document );
47
+ }
48
+ }(function( $, window, document, undefined ) {
49
+ 'use strict';
50
+ var DataTable = $.fn.dataTable;
26
51
 
27
- var factory = function( $, DataTable ) {
28
- "use strict";
29
52
 
30
53
  /**
31
54
  * Responsive is a plug-in for the DataTables library that makes use of
@@ -64,7 +87,7 @@ var factory = function( $, DataTable ) {
64
87
  * @param {object} settings DataTables settings object for the host table
65
88
  * @param {object} [opts] Configuration options
66
89
  * @requires jQuery 1.7+
67
- * @requires DataTables 1.10.1+
90
+ * @requires DataTables 1.10.3+
68
91
  *
69
92
  * @example
70
93
  * $('#example').DataTable( {
@@ -74,13 +97,14 @@ var factory = function( $, DataTable ) {
74
97
  */
75
98
  var Responsive = function ( settings, opts ) {
76
99
  // 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';
100
+ if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.3' ) ) {
101
+ throw 'DataTables Responsive requires DataTables 1.10.3 or newer';
79
102
  }
80
103
 
81
104
  this.s = {
82
105
  dt: new DataTable.Api( settings ),
83
- columns: []
106
+ columns: [],
107
+ current: []
84
108
  };
85
109
 
86
110
  // Check if responsive has already been initialised on this table
@@ -98,7 +122,7 @@ var Responsive = function ( settings, opts ) {
98
122
  this._constructor();
99
123
  };
100
124
 
101
- Responsive.prototype = {
125
+ $.extend( Responsive.prototype, {
102
126
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
103
127
  * Constructor
104
128
  */
@@ -112,17 +136,43 @@ Responsive.prototype = {
112
136
  {
113
137
  var that = this;
114
138
  var dt = this.s.dt;
139
+ var dtPrivateSettings = dt.settings()[0];
115
140
 
116
141
  dt.settings()[0]._responsive = this;
117
142
 
118
- // Use DataTables' private throttle function to avoid processor thrashing
119
- $(window).on( 'resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle( function () {
143
+ // Use DataTables' throttle function to avoid processor thrashing on
144
+ // resize
145
+ $(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
120
146
  that._resize();
121
147
  } ) );
122
148
 
149
+ // DataTables doesn't currently trigger an event when a row is added, so
150
+ // we need to hook into its private API to enforce the hidden rows when
151
+ // new data is added
152
+ dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
153
+ if ( $.inArray( false, that.s.current ) !== -1 ) {
154
+ $('td, th', tr).each( function ( i ) {
155
+ var idx = dt.column.index( 'toData', i );
156
+
157
+ if ( that.s.current[idx] === false ) {
158
+ $(this).css('display', 'none');
159
+ }
160
+ } );
161
+ }
162
+ } );
163
+
123
164
  // Destroy event handler
124
165
  dt.on( 'destroy.dtr', function () {
125
- $(window).off( 'resize.dtr orientationchange.dtr draw.dtr' );
166
+ dt.off( '.dtr' );
167
+ $( dt.table().body() ).off( '.dtr' );
168
+ $(window).off( 'resize.dtr orientationchange.dtr' );
169
+
170
+ // Restore the columns that we've hidden
171
+ $.each( that.s.current, function ( i, val ) {
172
+ if ( val === false ) {
173
+ that._setColumnVis( i, true );
174
+ }
175
+ } );
126
176
  } );
127
177
 
128
178
  // Reorder the breakpoints array here in case they have been added out
@@ -132,40 +182,41 @@ Responsive.prototype = {
132
182
  a.width > b.width ? -1 : 0;
133
183
  } );
134
184
 
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
185
  this._classLogic();
141
186
  this._resizeAuto();
142
187
 
143
188
  // Details handler
144
189
  var details = this.c.details;
145
- if ( details.type ) {
190
+ if ( details.type !== false ) {
146
191
  that._detailsInit();
147
- this._detailsVis();
148
192
 
149
- dt.on( 'column-visibility.dtr', function () {
150
- that._detailsVis();
193
+ // DataTables will trigger this event on every column it shows and
194
+ // hides individually
195
+ dt.on( 'column-visibility.dtr', function (e, ctx, col, vis) {
196
+ that._classLogic();
197
+ that._resizeAuto();
198
+ that._resize();
151
199
  } );
152
200
 
153
- // Redraw the details box on each draw. This is used until
154
- // DataTables implements a native `updated` event for rows
201
+ // Redraw the details box on each draw which will happen if the data
202
+ // has changed. This is used until DataTables implements a native
203
+ // `updated` event for rows
155
204
  dt.on( 'draw.dtr', function () {
156
- dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
157
- var row = dt.row( idx );
158
-
159
- if ( row.child.isShown() ) {
160
- var info = that.c.details.renderer( dt, idx );
161
- row.child( info, 'child' ).show();
162
- }
163
- } );
205
+ that._redrawChildren();
164
206
  } );
165
207
 
166
208
  $(dt.table().node()).addClass( 'dtr-'+details.type );
167
209
  }
168
210
 
211
+ dt.on( 'column-reorder.dtr', function (e, settings, details) {
212
+ // This requires ColReorder 1.2.1 or newer
213
+ if ( details.drop ) {
214
+ that._classLogic();
215
+ that._resizeAuto();
216
+ that._resize();
217
+ }
218
+ } );
219
+
169
220
  // First pass - draw the table for the current viewport size
170
221
  this._resize();
171
222
  },
@@ -193,6 +244,24 @@ Responsive.prototype = {
193
244
  var columns = this.s.columns;
194
245
  var i, ien;
195
246
 
247
+ // Create an array that defines the column ordering based first on the
248
+ // column's priority, and secondly the column index. This allows the
249
+ // columns to be removed from the right if the priority matches
250
+ var order = columns
251
+ .map( function ( col, idx ) {
252
+ return {
253
+ columnIdx: idx,
254
+ priority: col.priority
255
+ };
256
+ } )
257
+ .sort( function ( a, b ) {
258
+ if ( a.priority !== b.priority ) {
259
+ return a.priority - b.priority;
260
+ }
261
+ return a.columnIdx - b.columnIdx;
262
+ } );
263
+
264
+
196
265
  // Class logic - determine which columns are in this breakpoint based
197
266
  // on the classes. If no class control (i.e. `auto`) then `-` is used
198
267
  // to indicate this to the rest of the function
@@ -234,23 +303,25 @@ Responsive.prototype = {
234
303
  }
235
304
  }
236
305
 
237
- // Allow columns to be shown (counting from the left) until we run out
238
- // of room
306
+ // Allow columns to be shown (counting by priority and then right to
307
+ // left) until we run out of room
239
308
  var empty = false;
240
- for ( i=0, ien=display.length ; i<ien ; i++ ) {
241
- if ( display[i] === '-' && ! columns[i].control ) {
309
+ for ( i=0, ien=order.length ; i<ien ; i++ ) {
310
+ var colIdx = order[i].columnIdx;
311
+
312
+ if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
242
313
  // Once we've found a column that won't fit we don't let any
243
314
  // others display either, or columns might disappear in the
244
315
  // middle of the table
245
- if ( empty || usedWidth - columns[i].minWidth < 0 ) {
316
+ if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
246
317
  empty = true;
247
- display[i] = false;
318
+ display[colIdx] = false;
248
319
  }
249
320
  else {
250
- display[i] = true;
321
+ display[colIdx] = true;
251
322
  }
252
323
 
253
- usedWidth -= columns[i].minWidth;
324
+ usedWidth -= columns[colIdx].minWidth;
254
325
  }
255
326
  }
256
327
 
@@ -297,15 +368,25 @@ Responsive.prototype = {
297
368
  var that = this;
298
369
  var calc = {};
299
370
  var breakpoints = this.c.breakpoints;
300
- var columns = this.s.dt.columns().eq(0).map( function (i) {
301
- var className = this.column(i).header().className;
371
+ var dt = this.s.dt;
372
+ var columns = dt.columns().eq(0).map( function (i) {
373
+ var column = this.column(i);
374
+ var className = column.header().className;
375
+ var priority = dt.settings()[0].aoColumns[i].responsivePriority;
376
+
377
+ if ( priority === undefined ) {
378
+ priority = $(column.header).data('priority') !== undefined ?
379
+ $(column.header).data('priority') * 1 :
380
+ 10000;
381
+ }
302
382
 
303
383
  return {
304
384
  className: className,
305
385
  includeIn: [],
306
386
  auto: false,
307
387
  control: false,
308
- never: className.match(/\bnever\b/) ? true : false
388
+ never: className.match(/\bnever\b/) ? true : false,
389
+ priority: priority
309
390
  };
310
391
  } );
311
392
 
@@ -346,8 +427,7 @@ Responsive.prototype = {
346
427
  }
347
428
  }
348
429
  else if ( operator === 'not-' ) {
349
- // Add all but this breakpoint (xxx need extra information)
350
-
430
+ // Add all but this breakpoint
351
431
  for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
352
432
  if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
353
433
  add( colIdx, breakpoints[i].name );
@@ -374,7 +454,7 @@ Responsive.prototype = {
374
454
  } );
375
455
  return;
376
456
  }
377
- else if ( className === 'none' || className === 'never' ) {
457
+ else if ( className === 'none' || col.never ) {
378
458
  // Include in none (default) and no auto
379
459
  hasClass = true;
380
460
  return;
@@ -418,6 +498,30 @@ Responsive.prototype = {
418
498
  },
419
499
 
420
500
 
501
+ /**
502
+ * Show the details for the child row
503
+ *
504
+ * @param {DataTables.Api} row API instance for the row
505
+ * @param {boolean} update Update flag
506
+ * @private
507
+ */
508
+ _detailsDisplay: function ( row, update )
509
+ {
510
+ var that = this;
511
+ var dt = this.s.dt;
512
+
513
+ var res = this.c.details.display( row, update, function () {
514
+ return that.c.details.renderer(
515
+ dt, row[0], that._detailsObj(row[0])
516
+ );
517
+ } );
518
+
519
+ if ( res === true || res === false ) {
520
+ $(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
521
+ }
522
+ },
523
+
524
+
421
525
  /**
422
526
  * Initialisation for the details handler
423
527
  *
@@ -434,109 +538,93 @@ Responsive.prototype = {
434
538
  details.target = 'td:first-child';
435
539
  }
436
540
 
541
+ // Keyboard accessibility
542
+ dt.on( 'draw.dtr', function () {
543
+ that._tabIndexes();
544
+ } );
545
+ that._tabIndexes(); // Initial draw has already happened
546
+
547
+ $( dt.table().body() ).on( 'keyup.dtr', 'td', function (e) {
548
+ if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
549
+ $(this).click();
550
+ }
551
+ } );
552
+
437
553
  // type.target can be a string jQuery selector or a column index
438
554
  var target = details.target;
439
555
  var selector = typeof target === 'string' ? target : 'td';
440
556
 
441
557
  // Click handler to show / hide the details rows when they are available
442
- $( dt.table().body() ).on( 'click', selector, function (e) {
443
- // If the table is not collapsed (i.e. there is no hidden columns)
444
- // then take no action
445
- if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
446
- return;
447
- }
558
+ $( dt.table().body() )
559
+ .on( 'mousedown.dtr', selector, function (e) {
560
+ // For mouse users, prevent the focus ring from showing
561
+ e.preventDefault();
562
+ } )
563
+ .on( 'click.dtr', selector, function () {
564
+ // If the table is not collapsed (i.e. there is no hidden columns)
565
+ // then take no action
566
+ if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
567
+ return;
568
+ }
448
569
 
449
- // Check that the row is actually a DataTable's controlled node
450
- if ( ! dt.row( $(this).closest('tr') ).length ) {
451
- return;
452
- }
570
+ // Check that the row is actually a DataTable's controlled node
571
+ if ( ! dt.row( $(this).closest('tr') ).length ) {
572
+ return;
573
+ }
453
574
 
454
- // For column index, we determine if we should act or not in the
455
- // handler - otherwise it is already okay
456
- if ( typeof target === 'number' ) {
457
- var targetIdx = target < 0 ?
458
- dt.columns().eq(0).length + target :
459
- target;
575
+ // For column index, we determine if we should act or not in the
576
+ // handler - otherwise it is already okay
577
+ if ( typeof target === 'number' ) {
578
+ var targetIdx = target < 0 ?
579
+ dt.columns().eq(0).length + target :
580
+ target;
460
581
 
461
- if ( dt.cell( this ).index().column !== targetIdx ) {
462
- return;
582
+ if ( dt.cell( this ).index().column !== targetIdx ) {
583
+ return;
584
+ }
463
585
  }
464
- }
465
586
 
466
- // $().closest() includes itself in its check
467
- var row = dt.row( $(this).closest('tr') );
587
+ // $().closest() includes itself in its check
588
+ var row = dt.row( $(this).closest('tr') );
468
589
 
469
- if ( row.child.isShown() ) {
470
- row.child( false );
471
- $( row.node() ).removeClass( 'parent' );
472
- }
473
- else {
474
- var info = that.c.details.renderer( dt, row[0] );
475
- row.child( info, 'child' ).show();
476
- $( row.node() ).addClass( 'parent' );
477
- }
478
- } );
590
+ // The renderer is given as a function so the caller can execute it
591
+ // only when they need (i.e. if hiding there is no point is running
592
+ // the renderer)
593
+ that._detailsDisplay( row, false );
594
+ } );
479
595
  },
480
596
 
481
597
 
482
598
  /**
483
- * Update the child rows in the table whenever the column visibility changes
484
- *
599
+ * Get the details to pass to a renderer for a row
600
+ * @param {int} rowIdx Row index
485
601
  * @private
486
602
  */
487
- _detailsVis: function ()
603
+ _detailsObj: function ( rowIdx )
488
604
  {
489
605
  var that = this;
490
606
  var dt = this.s.dt;
491
607
 
492
- // Find how many columns are hidden
493
- var hiddenColumns = dt.columns().indexes().filter( function ( idx ) {
494
- var col = dt.column( idx );
495
-
496
- if ( col.visible() ) {
497
- return null;
608
+ return $.map( this.s.columns, function( col, i ) {
609
+ if ( col.never ) {
610
+ return;
498
611
  }
499
612
 
500
- // Only counts as hidden if it doesn't have the `never` class
501
- return $( col.header() ).hasClass( 'never' ) ? null : idx;
613
+ return {
614
+ title: dt.settings()[0].aoColumns[ i ].sTitle,
615
+ data: dt.cell( rowIdx, i ).render( that.c.orthogonal ),
616
+ hidden: dt.column( i ).visible() && !that.s.current[ i ]
617
+ };
502
618
  } );
503
- var haveHidden = true;
504
-
505
- if ( hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[ hiddenColumns[0] ].control ) ) {
506
- haveHidden = false;
507
- }
508
-
509
- if ( haveHidden ) {
510
- // Show all existing child rows
511
- dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
512
- var row = dt.row( idx );
513
-
514
- if ( row.child() ) {
515
- var info = that.c.details.renderer( dt, row[0] );
516
-
517
- // The renderer can return false to have no child row
518
- if ( info === false ) {
519
- row.child.hide();
520
- }
521
- else {
522
- row.child( info, 'child' ).show();
523
- }
524
- }
525
- } );
526
- }
527
- else {
528
- // Hide all existing child rows
529
- dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
530
- dt.row( idx ).child.hide();
531
- } );
532
- }
533
619
  },
534
620
 
535
621
 
536
622
  /**
537
623
  * Find a breakpoint object from a name
624
+ *
538
625
  * @param {string} name Breakpoint name to find
539
626
  * @return {object} Breakpoint description object
627
+ * @private
540
628
  */
541
629
  _find: function ( name )
542
630
  {
@@ -550,6 +638,25 @@ Responsive.prototype = {
550
638
  },
551
639
 
552
640
 
641
+ /**
642
+ * Re-create the contents of the child rows as the display has changed in
643
+ * some way.
644
+ *
645
+ * @private
646
+ */
647
+ _redrawChildren: function ()
648
+ {
649
+ var that = this;
650
+ var dt = this.s.dt;
651
+
652
+ dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
653
+ var row = dt.row( idx );
654
+
655
+ that._detailsDisplay( dt.row( idx ), true );
656
+ } );
657
+ },
658
+
659
+
553
660
  /**
554
661
  * Alter the table display for a resized viewport. This involves first
555
662
  * determining what breakpoint the window currently is in, getting the
@@ -559,12 +666,14 @@ Responsive.prototype = {
559
666
  */
560
667
  _resize: function ()
561
668
  {
669
+ var that = this;
562
670
  var dt = this.s.dt;
563
671
  var width = $(window).width();
564
672
  var breakpoints = this.c.breakpoints;
565
673
  var breakpoint = breakpoints[0].name;
566
674
  var columns = this.s.columns;
567
675
  var i, ien;
676
+ var oldVis = this.s.current.slice();
568
677
 
569
678
  // Determine what breakpoint we are currently at
570
679
  for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
@@ -576,6 +685,7 @@ Responsive.prototype = {
576
685
 
577
686
  // Show the columns for that break point
578
687
  var columnsVis = this._columnsVisiblity( breakpoint );
688
+ this.s.current = columnsVis;
579
689
 
580
690
  // Set the class before the column visibility is changed so event
581
691
  // listeners know what the state is. Need to determine if there are
@@ -588,11 +698,20 @@ Responsive.prototype = {
588
698
  }
589
699
  }
590
700
 
591
- $( dt.table().node() ).toggleClass('collapsed', collapsedClass );
701
+ $( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
702
+
703
+ var changed = false;
592
704
 
593
705
  dt.columns().eq(0).each( function ( colIdx, i ) {
594
- dt.column( colIdx ).visible( columnsVis[i] );
706
+ if ( columnsVis[i] !== oldVis[i] ) {
707
+ changed = true;
708
+ that._setColumnVis( colIdx, columnsVis[i] );
709
+ }
595
710
  } );
711
+
712
+ if ( changed ) {
713
+ this._redrawChildren();
714
+ }
596
715
  },
597
716
 
598
717
 
@@ -627,42 +746,120 @@ Responsive.prototype = {
627
746
  var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
628
747
  var clonedBody = $( dt.table().body().cloneNode( false ) ).appendTo( clonedTable );
629
748
 
630
- $( dt.table().footer() ).clone( false ).appendTo( clonedTable );
631
-
632
- // This is a bit slow, but we need to get a clone of each row that
633
- // includes all columns. As such, try to do this as little as possible.
634
- dt.rows( { page: 'current' } ).indexes().flatten().each( function ( idx ) {
635
- var clone = dt.row( idx ).node().cloneNode( true );
636
-
637
- if ( dt.columns( ':hidden' ).flatten().length ) {
638
- $(clone).append( dt.cells( idx, ':hidden' ).nodes().to$().clone() );
639
- }
640
-
641
- $(clone).appendTo( clonedBody );
642
- } );
749
+ // Header
750
+ var headerCells = dt.columns()
751
+ .header()
752
+ .filter( function (idx) {
753
+ return dt.column(idx).visible();
754
+ } )
755
+ .to$()
756
+ .clone( false )
757
+ .css( 'display', 'table-cell' );
758
+
759
+ // Body rows - we don't need to take account of DataTables' column
760
+ // visibility since we implement our own here (hence the `display` set)
761
+ $(clonedBody)
762
+ .append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
763
+ .find( 'th, td' ).css( 'display', '' );
764
+
765
+ // Footer
766
+ var footer = dt.table().footer();
767
+ if ( footer ) {
768
+ var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
769
+ var footerCells = dt.columns()
770
+ .header()
771
+ .filter( function (idx) {
772
+ return dt.column(idx).visible();
773
+ } )
774
+ .to$()
775
+ .clone( false )
776
+ .css( 'display', 'table-cell' );
777
+
778
+ $('<tr/>')
779
+ .append( footerCells )
780
+ .appendTo( clonedFooter );
781
+ }
643
782
 
644
- var cells = dt.columns().header().to$().clone( false );
645
783
  $('<tr/>')
646
- .append( cells )
784
+ .append( headerCells )
647
785
  .appendTo( clonedHeader );
648
786
 
787
+ // In the inline case extra padding is applied to the first column to
788
+ // give space for the show / hide icon. We need to use this in the
789
+ // calculation
790
+ if ( this.c.details.type === 'inline' ) {
791
+ $(clonedTable).addClass( 'dtr-inline collapsed' );
792
+ }
793
+
649
794
  var inserted = $('<div/>')
650
795
  .css( {
651
796
  width: 1,
652
797
  height: 1,
653
798
  overflow: 'hidden'
654
799
  } )
655
- .append( clonedTable )
656
- .insertBefore( dt.table().node() );
800
+ .append( clonedTable );
801
+
802
+ inserted.insertBefore( dt.table().node() );
657
803
 
658
804
  // The cloned header now contains the smallest that each column can be
659
- dt.columns().eq(0).each( function ( idx ) {
660
- columns[idx].minWidth = cells[ idx ].offsetWidth || 0;
805
+ headerCells.each( function (i) {
806
+ var idx = dt.column.index( 'fromVisible', i );
807
+ columns[ idx ].minWidth = this.offsetWidth || 0;
661
808
  } );
662
809
 
663
810
  inserted.remove();
811
+ },
812
+
813
+ /**
814
+ * Set a column's visibility.
815
+ *
816
+ * We don't use DataTables' column visibility controls in order to ensure
817
+ * that column visibility can Responsive can no-exist. Since only IE8+ is
818
+ * supported (and all evergreen browsers of course) the control of the
819
+ * display attribute works well.
820
+ *
821
+ * @param {integer} col Column index
822
+ * @param {boolean} showHide Show or hide (true or false)
823
+ * @private
824
+ */
825
+ _setColumnVis: function ( col, showHide )
826
+ {
827
+ var dt = this.s.dt;
828
+ var display = showHide ? '' : 'none'; // empty string will remove the attr
829
+
830
+ $( dt.column( col ).header() ).css( 'display', display );
831
+ $( dt.column( col ).footer() ).css( 'display', display );
832
+ dt.column( col ).nodes().to$().css( 'display', display );
833
+ },
834
+
835
+
836
+ /**
837
+ * Update the cell tab indexes for keyboard accessibility. This is called on
838
+ * every table draw - that is potentially inefficient, but also the least
839
+ * complex option given that column visibility can change on the fly. Its a
840
+ * shame user-focus was removed from CSS 3 UI, as it would have solved this
841
+ * issue with a single CSS statement.
842
+ *
843
+ * @private
844
+ */
845
+ _tabIndexes: function ()
846
+ {
847
+ var dt = this.s.dt;
848
+ var cells = dt.cells( { page: 'current' } ).nodes().to$();
849
+ var ctx = dt.settings()[0];
850
+ var target = this.c.details.target;
851
+
852
+ cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
853
+
854
+ var selector = typeof target === 'number' ?
855
+ ':eq('+target+')' :
856
+ target;
857
+
858
+ $( selector, dt.rows( { page: 'current' } ).nodes() )
859
+ .attr( 'tabIndex', ctx.iTabIndex )
860
+ .data( 'dtr-keyboard', 1 );
664
861
  }
665
- };
862
+ } );
666
863
 
667
864
 
668
865
  /**
@@ -684,6 +881,110 @@ Responsive.breakpoints = [
684
881
  ];
685
882
 
686
883
 
884
+ /**
885
+ * Display methods - functions which define how the hidden data should be shown
886
+ * in the table.
887
+ *
888
+ * @namespace
889
+ * @name Responsive.defaults
890
+ * @static
891
+ */
892
+ Responsive.display = {
893
+ childRow: function ( row, update, render ) {
894
+ if ( update ) {
895
+ if ( $(row.node()).hasClass('parent') ) {
896
+ row.child( render(), 'child' ).show();
897
+
898
+ return true;
899
+ }
900
+ }
901
+ else {
902
+ if ( ! row.child.isShown() ) {
903
+ row.child( render(), 'child' ).show();
904
+ $( row.node() ).addClass( 'parent' );
905
+
906
+ return true;
907
+ }
908
+ else {
909
+ row.child( false );
910
+ $( row.node() ).removeClass( 'parent' );
911
+
912
+ return false;
913
+ }
914
+ }
915
+ },
916
+
917
+ childRowImmediate: function ( row, update, render ) {
918
+ if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
919
+ // User interaction and the row is show, or nothing to show
920
+ row.child( false );
921
+ $( row.node() ).removeClass( 'parent' );
922
+
923
+ return false;
924
+ }
925
+ else {
926
+ // Display
927
+ row.child( render(), 'child' ).show();
928
+ $( row.node() ).addClass( 'parent' );
929
+
930
+ return true;
931
+ }
932
+ },
933
+
934
+ // This is a wrapper so the modal options for Bootstrap and jQuery UI can
935
+ // have options passed into them. This specific one doesn't need to be a
936
+ // function but it is for consistency in the `modal` name
937
+ modal: function ( options ) {
938
+ return function ( row, update, render ) {
939
+ if ( ! update ) {
940
+ // Show a modal
941
+ var close = function () {
942
+ modal.remove(); // will tidy events for us
943
+ $(document).off( 'keypress.dtr' );
944
+ };
945
+
946
+ var modal = $('<div class="dtr-modal"/>')
947
+ .append( $('<div class="dtr-modal-display"/>')
948
+ .append( $('<div class="dtr-modal-content"/>')
949
+ .append( render() )
950
+ )
951
+ .append( $('<div class="dtr-modal-close">&times;</div>' )
952
+ .click( function () {
953
+ close();
954
+ } )
955
+ )
956
+ )
957
+ .append( $('<div class="dtr-modal-background"/>')
958
+ .click( function () {
959
+ close();
960
+ } )
961
+ )
962
+ .appendTo( 'body' );
963
+
964
+ if ( options && options.header ) {
965
+ modal.find( 'div.dtr-modal-content' ).prepend(
966
+ '<h2>'+options.header( row )+'</h2>'
967
+ );
968
+ }
969
+
970
+ $(document).on( 'keyup.dtr', function (e) {
971
+ if ( e.keyCode === 27 ) {
972
+ e.stopPropagation();
973
+
974
+ close();
975
+ }
976
+ } );
977
+ }
978
+ else {
979
+ $('div.dtr-modal-content')
980
+ .empty()
981
+ .append( render() );
982
+ }
983
+ };
984
+ }
985
+ };
986
+
987
+
687
988
  /**
688
989
  * Responsive default settings for initialisation
689
990
  *
@@ -719,6 +1020,7 @@ Responsive.defaults = {
719
1020
  *
720
1021
  * The object consists of the following properties:
721
1022
  *
1023
+ * * `display` - A function that is used to show and hide the hidden details
722
1024
  * * `renderer` - function that is called for display of the child row data.
723
1025
  * The default function will show the data from the hidden columns
724
1026
  * * `target` - Used as the selector for what objects to attach the child
@@ -729,36 +1031,21 @@ Responsive.defaults = {
729
1031
  * @type {Object|string}
730
1032
  */
731
1033
  details: {
732
- renderer: function ( api, rowIdx ) {
733
- var data = api.cells( rowIdx, ':hidden' ).eq(0).map( function ( cell ) {
734
- var header = $( api.column( cell.column ).header() );
735
- var idx = api.cell( cell ).index();
1034
+ display: Responsive.display.childRow,
736
1035
 
737
- if ( header.hasClass( 'control' ) || header.hasClass( 'never' ) ) {
738
- return '';
739
- }
740
-
741
- // Use a non-public DT API method to render the data for display
742
- // This needs to be updated when DT adds a suitable method for
743
- // this type of data retrieval
744
- var dtPrivate = api.settings()[0];
745
- var cellData = dtPrivate.oApi._fnGetCellData(
746
- dtPrivate, idx.row, idx.column, 'display'
747
- );
748
- var title = header.text();
749
- if ( title ) {
750
- title = title + ':';
751
- }
752
-
753
- return '<li data-dtr-index="'+idx.column+'">'+
1036
+ renderer: function ( api, rowIdx, columns ) {
1037
+ var data = $.map( columns, function ( col, i ) {
1038
+ return col.hidden ?
1039
+ '<li data-dtr-index="'+i+'">'+
754
1040
  '<span class="dtr-title">'+
755
- title+
1041
+ col.title+
756
1042
  '</span> '+
757
1043
  '<span class="dtr-data">'+
758
- cellData+
1044
+ col.data+
759
1045
  '</span>'+
760
- '</li>';
761
- } ).toArray().join('');
1046
+ '</li>' :
1047
+ '';
1048
+ } ).join('');
762
1049
 
763
1050
  return data ?
764
1051
  $('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
@@ -768,7 +1055,15 @@ Responsive.defaults = {
768
1055
  target: 0,
769
1056
 
770
1057
  type: 'inline'
771
- }
1058
+ },
1059
+
1060
+ /**
1061
+ * Orthogonal data request option. This is used to define the data type
1062
+ * requested when Responsive gets the data to show in the child row.
1063
+ *
1064
+ * @type {String}
1065
+ */
1066
+ orthogonal: 'display'
772
1067
  };
773
1068
 
774
1069
 
@@ -808,6 +1103,14 @@ Api.register( 'responsive.recalc()', function () {
808
1103
  } );
809
1104
  } );
810
1105
 
1106
+ Api.register( 'responsive.hasHidden()', function () {
1107
+ var ctx = this.context[0];
1108
+
1109
+ return ctx._responsive ?
1110
+ $.inArray( false, ctx._responsive.s.current ) !== -1 :
1111
+ false;
1112
+ } );
1113
+
811
1114
 
812
1115
  /**
813
1116
  * Version information
@@ -815,7 +1118,7 @@ Api.register( 'responsive.recalc()', function () {
815
1118
  * @name Responsive.version
816
1119
  * @static
817
1120
  */
818
- Responsive.version = '1.0.5';
1121
+ Responsive.version = '2.0.0';
819
1122
 
820
1123
 
821
1124
  $.fn.dataTable.Responsive = Responsive;
@@ -833,8 +1136,6 @@ $(document).on( 'init.dt.dtr', function (e, settings, json) {
833
1136
  settings.oInit.responsive ||
834
1137
  DataTable.defaults.responsive
835
1138
  ) {
836
- console.log( e.namespace );
837
-
838
1139
  var init = settings.oInit.responsive;
839
1140
 
840
1141
  if ( init !== false ) {
@@ -843,22 +1144,6 @@ $(document).on( 'init.dt.dtr', function (e, settings, json) {
843
1144
  }
844
1145
  } );
845
1146
 
846
- return Responsive;
847
- }; // /factory
848
-
849
1147
 
850
- // Define as an AMD module if possible
851
- if ( typeof define === 'function' && define.amd ) {
852
- define( ['jquery', 'datatables'], factory );
853
- }
854
- else if ( typeof exports === 'object' ) {
855
- // Node/CommonJS
856
- factory( require('jquery'), require('datatables') );
857
- }
858
- else if ( jQuery && !jQuery.fn.dataTable.Responsive ) {
859
- // Otherwise simply initialise as normal, stopping multiple evaluation
860
- factory( jQuery, jQuery.fn.dataTable );
861
- }
862
-
863
-
864
- })(window, document);
1148
+ return Responsive;
1149
+ }));