datatables.net-select 1.6.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,77 +1,81 @@
1
- /*! Select for DataTables 1.6.2
1
+ /*! Select for DataTables 2.0.0
2
2
  * © SpryMedia Ltd - datatables.net/license/mit
3
3
  */
4
4
 
5
- import $ from 'jquery';
5
+ import jQuery from 'jquery';
6
6
  import DataTable from 'datatables.net';
7
7
 
8
+ // Allow reassignment of the $ variable
9
+ let $ = jQuery;
10
+
8
11
 
9
12
  // Version information for debugger
10
13
  DataTable.select = {};
11
14
 
12
- DataTable.select.version = '1.6.2';
15
+ DataTable.select.version = '2.0.0';
13
16
 
14
- DataTable.select.init = function ( dt ) {
17
+ DataTable.select.init = function (dt) {
15
18
  var ctx = dt.settings()[0];
16
19
 
20
+ if (!DataTable.versionCheck('2')) {
21
+ throw 'Warning: Select requires DataTables 2 or newer';
22
+ }
23
+
17
24
  if (ctx._select) {
18
25
  return;
19
26
  }
20
27
 
21
28
  var savedSelected = dt.state.loaded();
22
29
 
23
- var selectAndSave = function(e, settings, data) {
24
- if(data === null || data.select === undefined) {
30
+ var selectAndSave = function (e, settings, data) {
31
+ if (data === null || data.select === undefined) {
25
32
  return;
26
33
  }
27
34
 
28
35
  // Clear any currently selected rows, before restoring state
29
36
  // None will be selected on first initialisation
30
- if (dt.rows({selected: true}).any()) {
37
+ if (dt.rows({ selected: true }).any()) {
31
38
  dt.rows().deselect();
32
39
  }
33
40
  if (data.select.rows !== undefined) {
34
41
  dt.rows(data.select.rows).select();
35
42
  }
36
43
 
37
- if (dt.columns({selected: true}).any()) {
44
+ if (dt.columns({ selected: true }).any()) {
38
45
  dt.columns().deselect();
39
46
  }
40
47
  if (data.select.columns !== undefined) {
41
48
  dt.columns(data.select.columns).select();
42
49
  }
43
50
 
44
- if (dt.cells({selected: true}).any()) {
51
+ if (dt.cells({ selected: true }).any()) {
45
52
  dt.cells().deselect();
46
53
  }
47
54
  if (data.select.cells !== undefined) {
48
- for(var i = 0; i < data.select.cells.length; i++) {
55
+ for (var i = 0; i < data.select.cells.length; i++) {
49
56
  dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
50
57
  }
51
58
  }
52
59
 
53
60
  dt.state.save();
54
- }
55
-
56
- dt
57
- .on('stateSaveParams', function(e, settings, data) {
58
- data.select = {};
59
- data.select.rows = dt.rows({selected:true}).ids(true).toArray();
60
- data.select.columns = dt.columns({selected:true})[0];
61
- data.select.cells = dt.cells({selected:true})[0].map(function(coords) {
62
- return {row: dt.row(coords.row).id(true), column: coords.column}
63
- });
64
- })
61
+ };
62
+
63
+ dt.on('stateSaveParams', function (e, settings, data) {
64
+ data.select = {};
65
+ data.select.rows = dt.rows({ selected: true }).ids(true).toArray();
66
+ data.select.columns = dt.columns({ selected: true })[0];
67
+ data.select.cells = dt.cells({ selected: true })[0].map(function (coords) {
68
+ return { row: dt.row(coords.row).id(true), column: coords.column };
69
+ });
70
+ })
65
71
  .on('stateLoadParams', selectAndSave)
66
- .one('init', function() {
72
+ .one('init', function () {
67
73
  selectAndSave(undefined, undefined, savedSelected);
68
74
  });
69
75
 
70
76
  var init = ctx.oInit.select;
71
77
  var defaults = DataTable.defaults.select;
72
- var opts = init === undefined ?
73
- defaults :
74
- init;
78
+ var opts = init === undefined ? defaults : init;
75
79
 
76
80
  // Set defaults
77
81
  var items = 'row';
@@ -81,37 +85,40 @@ DataTable.select.init = function ( dt ) {
81
85
  var info = true;
82
86
  var selector = 'td, th';
83
87
  var className = 'selected';
88
+ var headerCheckbox = true;
84
89
  var setStyle = false;
85
90
 
86
- ctx._select = {};
91
+ ctx._select = {
92
+ infoEls: []
93
+ };
87
94
 
88
95
  // Initialisation customisations
89
- if ( opts === true ) {
96
+ if (opts === true) {
90
97
  style = 'os';
91
98
  setStyle = true;
92
99
  }
93
- else if ( typeof opts === 'string' ) {
100
+ else if (typeof opts === 'string') {
94
101
  style = opts;
95
102
  setStyle = true;
96
103
  }
97
- else if ( $.isPlainObject( opts ) ) {
98
- if ( opts.blurable !== undefined ) {
104
+ else if ($.isPlainObject(opts)) {
105
+ if (opts.blurable !== undefined) {
99
106
  blurable = opts.blurable;
100
107
  }
101
-
102
- if ( opts.toggleable !== undefined ) {
108
+
109
+ if (opts.toggleable !== undefined) {
103
110
  toggleable = opts.toggleable;
104
111
  }
105
112
 
106
- if ( opts.info !== undefined ) {
113
+ if (opts.info !== undefined) {
107
114
  info = opts.info;
108
115
  }
109
116
 
110
- if ( opts.items !== undefined ) {
117
+ if (opts.items !== undefined) {
111
118
  items = opts.items;
112
119
  }
113
120
 
114
- if ( opts.style !== undefined ) {
121
+ if (opts.style !== undefined) {
115
122
  style = opts.style;
116
123
  setStyle = true;
117
124
  }
@@ -120,40 +127,41 @@ DataTable.select.init = function ( dt ) {
120
127
  setStyle = true;
121
128
  }
122
129
 
123
- if ( opts.selector !== undefined ) {
130
+ if (opts.selector !== undefined) {
124
131
  selector = opts.selector;
125
132
  }
126
133
 
127
- if ( opts.className !== undefined ) {
134
+ if (opts.className !== undefined) {
128
135
  className = opts.className;
129
136
  }
137
+
138
+ if (opts.headerCheckbox !== undefined) {
139
+ headerCheckbox = opts.headerCheckbox;
140
+ }
130
141
  }
131
142
 
132
- dt.select.selector( selector );
133
- dt.select.items( items );
134
- dt.select.style( style );
135
- dt.select.blurable( blurable );
136
- dt.select.toggleable( toggleable );
137
- dt.select.info( info );
143
+ dt.select.selector(selector);
144
+ dt.select.items(items);
145
+ dt.select.style(style);
146
+ dt.select.blurable(blurable);
147
+ dt.select.toggleable(toggleable);
148
+ dt.select.info(info);
138
149
  ctx._select.className = className;
139
150
 
140
-
141
- // Sort table based on selected rows. Requires Select Datatables extension
142
- $.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) {
143
- return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) {
144
- if ( settings._select.items === 'row' ) {
145
- return $( td ).parent().hasClass( settings._select.className );
146
- } else if ( settings._select.items === 'cell' ) {
147
- return $( td ).hasClass( settings._select.className );
148
- }
149
- return false;
150
- });
151
- };
152
-
153
151
  // If the init options haven't enabled select, but there is a selectable
154
152
  // class name, then enable
155
- if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
156
- dt.select.style( 'os' );
153
+ if (!setStyle && $(dt.table().node()).hasClass('selectable')) {
154
+ dt.select.style('os');
155
+ }
156
+
157
+ // Insert a checkbox into the header if needed - might need to wait
158
+ // for init complete, or it might already be done
159
+ if (headerCheckbox) {
160
+ initCheckboxHeader(dt);
161
+
162
+ dt.on('init', function () {
163
+ initCheckboxHeader(dt);
164
+ });
157
165
  }
158
166
  };
159
167
 
@@ -206,6 +214,7 @@ The `_select` object contains the following properties:
206
214
  on the row
207
215
  info:boolean - If the selection summary should be shown in the table
208
216
  information elements
217
+ infoEls:element[] - List of HTML elements with info elements for a table
209
218
  }
210
219
  ```
211
220
 
@@ -221,7 +230,6 @@ handler that will select the items using the API methods.
221
230
 
222
231
  */
223
232
 
224
-
225
233
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
226
234
  * Local functions
227
235
  */
@@ -234,84 +242,87 @@ handler that will select the items using the API methods.
234
242
  * in the visible grid rather than by index in sequence. For example, if you
235
243
  * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
236
244
  * should also be selected (and not 1-3, 1-4. etc)
237
- *
245
+ *
238
246
  * @param {DataTable.Api} dt DataTable
239
247
  * @param {object} idx Cell index to select to
240
248
  * @param {object} last Cell index to select from
241
249
  * @private
242
250
  */
243
- function cellRange( dt, idx, last )
244
- {
251
+ function cellRange(dt, idx, last) {
245
252
  var indexes;
246
253
  var columnIndexes;
247
254
  var rowIndexes;
248
- var selectColumns = function ( start, end ) {
249
- if ( start > end ) {
255
+ var selectColumns = function (start, end) {
256
+ if (start > end) {
250
257
  var tmp = end;
251
258
  end = start;
252
259
  start = tmp;
253
260
  }
254
-
261
+
255
262
  var record = false;
256
- return dt.columns( ':visible' ).indexes().filter( function (i) {
257
- if ( i === start ) {
258
- record = true;
259
- }
260
-
261
- if ( i === end ) { // not else if, as start might === end
262
- record = false;
263
- return true;
264
- }
263
+ return dt
264
+ .columns(':visible')
265
+ .indexes()
266
+ .filter(function (i) {
267
+ if (i === start) {
268
+ record = true;
269
+ }
265
270
 
266
- return record;
267
- } );
271
+ if (i === end) {
272
+ // not else if, as start might === end
273
+ record = false;
274
+ return true;
275
+ }
276
+
277
+ return record;
278
+ });
268
279
  };
269
280
 
270
- var selectRows = function ( start, end ) {
271
- var indexes = dt.rows( { search: 'applied' } ).indexes();
281
+ var selectRows = function (start, end) {
282
+ var indexes = dt.rows({ search: 'applied' }).indexes();
272
283
 
273
284
  // Which comes first - might need to swap
274
- if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) {
285
+ if (indexes.indexOf(start) > indexes.indexOf(end)) {
275
286
  var tmp = end;
276
287
  end = start;
277
288
  start = tmp;
278
289
  }
279
290
 
280
291
  var record = false;
281
- return indexes.filter( function (i) {
282
- if ( i === start ) {
292
+ return indexes.filter(function (i) {
293
+ if (i === start) {
283
294
  record = true;
284
295
  }
285
-
286
- if ( i === end ) {
296
+
297
+ if (i === end) {
287
298
  record = false;
288
299
  return true;
289
300
  }
290
301
 
291
302
  return record;
292
- } );
303
+ });
293
304
  };
294
305
 
295
- if ( ! dt.cells( { selected: true } ).any() && ! last ) {
306
+ if (!dt.cells({ selected: true }).any() && !last) {
296
307
  // select from the top left cell to this one
297
- columnIndexes = selectColumns( 0, idx.column );
298
- rowIndexes = selectRows( 0 , idx.row );
308
+ columnIndexes = selectColumns(0, idx.column);
309
+ rowIndexes = selectRows(0, idx.row);
299
310
  }
300
311
  else {
301
312
  // Get column indexes between old and new
302
- columnIndexes = selectColumns( last.column, idx.column );
303
- rowIndexes = selectRows( last.row , idx.row );
313
+ columnIndexes = selectColumns(last.column, idx.column);
314
+ rowIndexes = selectRows(last.row, idx.row);
304
315
  }
305
316
 
306
- indexes = dt.cells( rowIndexes, columnIndexes ).flatten();
317
+ indexes = dt.cells(rowIndexes, columnIndexes).flatten();
307
318
 
308
- if ( ! dt.cells( idx, { selected: true } ).any() ) {
319
+ if (!dt.cells(idx, { selected: true }).any()) {
309
320
  // Select range
310
- dt.cells( indexes ).select();
321
+ dt.cells(indexes).select();
311
322
  }
312
323
  else {
313
324
  // Deselect range
314
- dt.cells( indexes ).deselect();
325
+ dt.cells(indexes).deselect();
315
326
  }
316
327
  }
317
328
 
@@ -321,17 +332,16 @@ function cellRange( dt, idx, last )
321
332
  * @param {DataTable.Api} dt DataTable to remove events from
322
333
  * @private
323
334
  */
324
- function disableMouseSelection( dt )
325
- {
335
+ function disableMouseSelection(dt) {
326
336
  var ctx = dt.settings()[0];
327
337
  var selector = ctx._select.selector;
328
338
 
329
- $( dt.table().container() )
330
- .off( 'mousedown.dtSelect', selector )
331
- .off( 'mouseup.dtSelect', selector )
332
- .off( 'click.dtSelect', selector );
339
+ $(dt.table().container())
340
+ .off('mousedown.dtSelect', selector)
341
+ .off('mouseup.dtSelect', selector)
342
+ .off('click.dtSelect', selector);
333
343
 
334
- $('body').off( 'click.dtSelect' + _safeId(dt.table().node()) );
344
+ $('body').off('click.dtSelect' + _safeId(dt.table().node()));
335
345
  }
336
346
 
337
347
  /**
@@ -340,121 +350,123 @@ function disableMouseSelection( dt )
340
350
  * @param {DataTable.Api} dt DataTable to remove events from
341
351
  * @private
342
352
  */
343
- function enableMouseSelection ( dt )
344
- {
345
- var container = $( dt.table().container() );
353
+ function enableMouseSelection(dt) {
354
+ var container = $(dt.table().container());
346
355
  var ctx = dt.settings()[0];
347
356
  var selector = ctx._select.selector;
348
357
  var matchSelection;
349
358
 
350
359
  container
351
- .on( 'mousedown.dtSelect', selector, function(e) {
360
+ .on('mousedown.dtSelect', selector, function (e) {
352
361
  // Disallow text selection for shift clicking on the table so multi
353
362
  // element selection doesn't look terrible!
354
- if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
363
+ if (e.shiftKey || e.metaKey || e.ctrlKey) {
355
364
  container
356
- .css( '-moz-user-select', 'none' )
365
+ .css('-moz-user-select', 'none')
357
366
  .one('selectstart.dtSelect', selector, function () {
358
367
  return false;
359
- } );
368
+ });
360
369
  }
361
370
 
362
- if ( window.getSelection ) {
371
+ if (window.getSelection) {
363
372
  matchSelection = window.getSelection();
364
373
  }
365
- } )
366
- .on( 'mouseup.dtSelect', selector, function() {
374
+ })
375
+ .on('mouseup.dtSelect', selector, function () {
367
376
  // Allow text selection to occur again, Mozilla style (tested in FF
368
377
  // 35.0.1 - still required)
369
- container.css( '-moz-user-select', '' );
370
- } )
371
- .on( 'click.dtSelect', selector, function ( e ) {
378
+ container.css('-moz-user-select', '');
379
+ })
380
+ .on('click.dtSelect', selector, function (e) {
372
381
  var items = dt.select.items();
373
382
  var idx;
374
383
 
375
384
  // If text was selected (click and drag), then we shouldn't change
376
385
  // the row's selected state
377
- if ( matchSelection ) {
386
+ if (matchSelection) {
378
387
  var selection = window.getSelection();
379
388
 
380
389
  // If the element that contains the selection is not in the table, we can ignore it
381
390
  // This can happen if the developer selects text from the click event
382
- if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) {
383
- if ( selection !== matchSelection ) {
391
+ if (
392
+ !selection.anchorNode ||
393
+ $(selection.anchorNode).closest('table')[0] === dt.table().node()
394
+ ) {
395
+ if (selection !== matchSelection) {
384
396
  return;
385
397
  }
386
398
  }
387
399
  }
388
400
 
389
401
  var ctx = dt.settings()[0];
390
- var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.');
402
+ var container = dt.table().container();
391
403
 
392
404
  // Ignore clicks inside a sub-table
393
- if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) {
405
+ if ($(e.target).closest('div.dt-container')[0] != container) {
394
406
  return;
395
407
  }
396
408
 
397
- var cell = dt.cell( $(e.target).closest('td, th') );
409
+ var cell = dt.cell($(e.target).closest('td, th'));
398
410
 
399
411
  // Check the cell actually belongs to the host DataTable (so child
400
412
  // rows, etc, are ignored)
401
- if ( ! cell.any() ) {
413
+ if (!cell.any()) {
402
414
  return;
403
415
  }
404
416
 
405
417
  var event = $.Event('user-select.dt');
406
- eventTrigger( dt, event, [ items, cell, e ] );
418
+ eventTrigger(dt, event, [items, cell, e]);
407
419
 
408
- if ( event.isDefaultPrevented() ) {
420
+ if (event.isDefaultPrevented()) {
409
421
  return;
410
422
  }
411
423
 
412
424
  var cellIndex = cell.index();
413
- if ( items === 'row' ) {
425
+ if (items === 'row') {
414
426
  idx = cellIndex.row;
415
- typeSelect( e, dt, ctx, 'row', idx );
427
+ typeSelect(e, dt, ctx, 'row', idx);
416
428
  }
417
- else if ( items === 'column' ) {
429
+ else if (items === 'column') {
418
430
  idx = cell.index().column;
419
- typeSelect( e, dt, ctx, 'column', idx );
431
+ typeSelect(e, dt, ctx, 'column', idx);
420
432
  }
421
- else if ( items === 'cell' ) {
433
+ else if (items === 'cell') {
422
434
  idx = cell.index();
423
- typeSelect( e, dt, ctx, 'cell', idx );
435
+ typeSelect(e, dt, ctx, 'cell', idx);
424
436
  }
425
437
 
426
438
  ctx._select_lastCell = cellIndex;
427
- } );
439
+ });
428
440
 
429
441
  // Blurable
430
- $('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) {
431
- if ( ctx._select.blurable ) {
442
+ $('body').on('click.dtSelect' + _safeId(dt.table().node()), function (e) {
443
+ if (ctx._select.blurable) {
432
444
  // If the click was inside the DataTables container, don't blur
433
- if ( $(e.target).parents().filter( dt.table().container() ).length ) {
445
+ if ($(e.target).parents().filter(dt.table().container()).length) {
434
446
  return;
435
447
  }
436
448
 
437
449
  // Ignore elements which have been removed from the DOM (i.e. paging
438
450
  // buttons)
439
- if ( $(e.target).parents('html').length === 0 ) {
440
- return;
451
+ if ($(e.target).parents('html').length === 0) {
452
+ return;
441
453
  }
442
454
 
443
455
  // Don't blur in Editor form
444
- if ( $(e.target).parents('div.DTE').length ) {
456
+ if ($(e.target).parents('div.DTE').length) {
445
457
  return;
446
458
  }
447
459
 
448
460
  var event = $.Event('select-blur.dt');
449
- eventTrigger( dt, event, [ e.target, e ] );
461
+ eventTrigger(dt, event, [e.target, e]);
450
462
 
451
- if ( event.isDefaultPrevented() ) {
463
+ if (event.isDefaultPrevented()) {
452
464
  return;
453
465
  }
454
466
 
455
- clear( ctx, true );
467
+ clear(ctx, true);
456
468
  }
457
- } );
469
+ });
458
470
  }
459
471
 
460
472
  /**
@@ -467,70 +479,125 @@ function enableMouseSelection ( dt )
467
479
  * triggering
468
480
  * @private
469
481
  */
470
- function eventTrigger ( api, type, args, any )
471
- {
472
- if ( any && ! api.flatten().length ) {
482
+ function eventTrigger(api, type, args, any) {
483
+ if (any && !api.flatten().length) {
473
484
  return;
474
485
  }
475
486
 
476
- if ( typeof type === 'string' ) {
477
- type = type +'.dt';
487
+ if (typeof type === 'string') {
488
+ type = type + '.dt';
478
489
  }
479
490
 
480
- args.unshift( api );
491
+ args.unshift(api);
481
492
 
482
- $(api.table().node()).trigger( type, args );
493
+ $(api.table().node()).trigger(type, args);
483
494
  }
484
495
 
485
496
  /**
486
497
  * Update the information element of the DataTable showing information about the
487
498
  * items selected. This is done by adding tags to the existing text
488
- *
499
+ *
489
500
  * @param {DataTable.Api} api DataTable to update
490
501
  * @private
491
502
  */
492
- function info ( api )
493
- {
494
- var ctx = api.settings()[0];
495
-
496
- if ( ! ctx._select.info || ! ctx.aanFeatures.i ) {
503
+ function info(api, node) {
504
+ if (api.select.style() === 'api' || api.select.info() === false) {
497
505
  return;
498
506
  }
499
507
 
500
- if ( api.select.style() === 'api' ) {
501
- return;
502
- }
508
+ var rows = api.rows({ selected: true }).flatten().length;
509
+ var columns = api.columns({ selected: true }).flatten().length;
510
+ var cells = api.cells({ selected: true }).flatten().length;
511
+
512
+ var add = function (el, name, num) {
513
+ el.append(
514
+ $('<span class="select-item"/>').append(
515
+ api.i18n(
516
+ 'select.' + name + 's',
517
+ { _: '%d ' + name + 's selected', 0: '', 1: '1 ' + name + ' selected' },
518
+ num
519
+ )
520
+ )
521
+ );
522
+ };
503
523
 
504
- var rows = api.rows( { selected: true } ).flatten().length;
505
- var columns = api.columns( { selected: true } ).flatten().length;
506
- var cells = api.cells( { selected: true } ).flatten().length;
524
+ var el = $(node);
525
+ var output = $('<span class="select-info"/>');
507
526
 
508
- var add = function ( el, name, num ) {
509
- el.append( $('<span class="select-item"/>').append( api.i18n(
510
- 'select.'+name+'s',
511
- { _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' },
512
- num
513
- ) ) );
514
- };
527
+ add(output, 'row', rows);
528
+ add(output, 'column', columns);
529
+ add(output, 'cell', cells);
515
530
 
516
- // Internal knowledge of DataTables to loop over all information elements
517
- $.each( ctx.aanFeatures.i, function ( i, el ) {
518
- el = $(el);
531
+ var existing = el.children('span.select-info');
519
532
 
520
- var output = $('<span class="select-info"/>');
521
- add( output, 'row', rows );
522
- add( output, 'column', columns );
523
- add( output, 'cell', cells );
533
+ if (existing.length) {
534
+ existing.remove();
535
+ }
524
536
 
525
- var exisiting = el.children('span.select-info');
526
- if ( exisiting.length ) {
527
- exisiting.remove();
528
- }
537
+ if (output.text() !== '') {
538
+ el.append(output);
539
+ }
540
+ }
529
541
 
530
- if ( output.text() !== '' ) {
531
- el.append( output );
542
+ /**
543
+ * Add a checkbox to the header for checkbox columns, allowing all rows to
544
+ * be selected, deselected or just to show the state.
545
+ *
546
+ * @param {*} dt API
547
+ */
548
+ function initCheckboxHeader( dt ) {
549
+ // Find any checkbox column(s)
550
+ dt.columns('.dt-select').every(function () {
551
+ var header = this.header();
552
+
553
+ if (! $('input', header).length) {
554
+ // If no checkbox yet, insert one
555
+ var input = $('<input>')
556
+ .attr({
557
+ class: 'dt-select-checkbox',
558
+ type: 'checkbox',
559
+ 'aria-label': dt.i18n('select.aria.headerCheckbox') || 'Select all rows'
560
+ })
561
+ .appendTo(header)
562
+ .on('change', function () {
563
+ if (this.checked) {
564
+ dt.rows({search: 'applied'}).select();
565
+ }
566
+ else {
567
+ dt.rows({selected: true}).deselect();
568
+ }
569
+ })
570
+ .on('click', function (e) {
571
+ e.stopPropagation();
572
+ });
573
+
574
+ // Update the header checkbox's state when the selection in the
575
+ // table changes
576
+ dt.on('draw select deselect', function (e, pass, type) {
577
+ if (type === 'row' || ! type) {
578
+ var count = dt.rows({selected: true}).count();
579
+ var search = dt.rows({search: 'applied', selected: true}).count();
580
+ var available = dt.rows({search: 'applied'}).count();
581
+
582
+ if (search && search <= count && search === available) {
583
+ input
584
+ .prop('checked', true)
585
+ .prop('indeterminate', false);
586
+ }
587
+ else if (search === 0 && count === 0) {
588
+ input
589
+ .prop('checked', false)
590
+ .prop('indeterminate', false);
591
+ }
592
+ else {
593
+ input
594
+ .prop('checked', false)
595
+ .prop('indeterminate', true);
596
+ }
597
+ }
598
+ });
532
599
  }
533
- } );
600
+ });
534
601
  }
535
602
 
536
603
  /**
@@ -543,41 +610,42 @@ function info ( api )
543
610
  * @param {DataTable.settings} ctx Settings object to operate on
544
611
  * @private
545
612
  */
546
- function init ( ctx ) {
547
- var api = new DataTable.Api( ctx );
613
+ function init(ctx) {
614
+ var api = new DataTable.Api(ctx);
548
615
  ctx._select_init = true;
549
616
 
550
617
  // Row callback so that classes can be added to rows and cells if the item
551
618
  // was selected before the element was created. This will happen with the
552
619
  // `deferRender` option enabled.
553
- //
620
+ //
554
621
  // This method of attaching to `aoRowCreatedCallback` is a hack until
555
622
  // DataTables has proper events for row manipulation If you are reviewing
556
623
  // this code to create your own plug-ins, please do not do this!
557
- ctx.aoRowCreatedCallback.push( {
558
- fn: function ( row, data, index ) {
624
+ ctx.aoRowCreatedCallback.push(function (row, data, index) {
559
625
  var i, ien;
560
- var d = ctx.aoData[ index ];
626
+ var d = ctx.aoData[index];
561
627
 
562
628
  // Row
563
- if ( d._select_selected ) {
564
- $( row ).addClass( ctx._select.className );
629
+ if (d._select_selected) {
630
+ $(row).addClass(ctx._select.className);
565
631
  }
566
632
 
567
633
  // Cells and columns - if separated out, we would need to do two
568
634
  // loops, so it makes sense to combine them into a single one
569
- for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) {
570
- if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) {
571
- $(d.anCells[i]).addClass( ctx._select.className );
635
+ for (i = 0, ien = ctx.aoColumns.length; i < ien; i++) {
636
+ if (
637
+ ctx.aoColumns[i]._select_selected ||
638
+ (d._selected_cells && d._selected_cells[i])
639
+ ) {
640
+ $(d.anCells[i]).addClass(ctx._select.className);
572
641
  }
573
642
  }
574
- },
575
- sName: 'select-deferRender'
576
- } );
643
+ }
644
+ );
577
645
 
578
646
  // On Ajax reload we want to reselect all rows which are currently selected,
579
647
  // if there is an rowId (i.e. a unique value to identify each row with)
580
- api.on( 'preXhr.dt.dtSelect', function (e, settings) {
648
+ api.on('preXhr.dt.dtSelect', function (e, settings) {
581
649
  if (settings !== api.settings()[0]) {
582
650
  // Not triggered by our DataTable!
583
651
  return;
@@ -585,47 +653,64 @@ function init ( ctx ) {
585
653
 
586
654
  // note that column selection doesn't need to be cached and then
587
655
  // reselected, as they are already selected
588
- var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) {
589
- return d !== undefined;
590
- } );
591
-
592
- var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) {
593
- var id = api.row( cellIdx.row ).id( true );
594
- return id ?
595
- { row: id, column: cellIdx.column } :
596
- undefined;
597
- } ).filter( function ( d ) {
598
- return d !== undefined;
599
- } );
656
+ var rows = api
657
+ .rows({ selected: true })
658
+ .ids(true)
659
+ .filter(function (d) {
660
+ return d !== undefined;
661
+ });
662
+
663
+ var cells = api
664
+ .cells({ selected: true })
665
+ .eq(0)
666
+ .map(function (cellIdx) {
667
+ var id = api.row(cellIdx.row).id(true);
668
+ return id ? { row: id, column: cellIdx.column } : undefined;
669
+ })
670
+ .filter(function (d) {
671
+ return d !== undefined;
672
+ });
600
673
 
601
674
  // On the next draw, reselect the currently selected items
602
- api.one( 'draw.dt.dtSelect', function () {
603
- api.rows( rows ).select();
675
+ api.one('draw.dt.dtSelect', function () {
676
+ api.rows(rows).select();
604
677
 
605
678
  // `cells` is not a cell index selector, so it needs a loop
606
- if ( cells.any() ) {
607
- cells.each( function ( id ) {
608
- api.cells( id.row, id.column ).select();
609
- } );
679
+ if (cells.any()) {
680
+ cells.each(function (id) {
681
+ api.cells(id.row, id.column).select();
682
+ });
610
683
  }
611
- } );
612
- } );
684
+ });
685
+ });
613
686
 
614
687
  // Update the table information element with selected item summary
615
- api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
616
- info( api );
688
+ api.on('info.dt', function (e, ctx, node) {
689
+ // Store the info node for updating on select / deselect
690
+ if (!ctx._select.infoEls.includes(node)) {
691
+ ctx._select.infoEls.push(node);
692
+ }
693
+
694
+ info(api, node);
695
+ });
696
+
697
+ api.on('select.dtSelect.dt deselect.dtSelect.dt', function () {
698
+ ctx._select.infoEls.forEach(function (el) {
699
+ info(api, el);
700
+ });
701
+
617
702
  api.state.save();
618
- } );
703
+ });
619
704
 
620
705
  // Clean up and release
621
- api.on( 'destroy.dtSelect', function () {
706
+ api.on('destroy.dtSelect', function () {
622
707
  // Remove class directly rather than calling deselect - which would trigger events
623
- $(api.rows({selected: true}).nodes()).removeClass(api.settings()[0]._select.className);
708
+ $(api.rows({ selected: true }).nodes()).removeClass(api.settings()[0]._select.className);
624
709
 
625
- disableMouseSelection( api );
626
- api.off( '.dtSelect' );
710
+ disableMouseSelection(api);
711
+ api.off('.dtSelect');
627
712
  $('body').off('.dtSelect' + _safeId(api.table().node()));
628
- } );
713
+ });
629
714
  }
630
715
 
631
716
  /**
@@ -638,38 +723,37 @@ function init ( ctx ) {
638
723
  * @param {object} last Item index to select from
639
724
  * @private
640
725
  */
641
- function rowColumnRange( dt, type, idx, last )
642
- {
726
+ function rowColumnRange(dt, type, idx, last) {
643
727
  // Add a range of rows from the last selected row to this one
644
- var indexes = dt[type+'s']( { search: 'applied' } ).indexes();
645
- var idx1 = $.inArray( last, indexes );
646
- var idx2 = $.inArray( idx, indexes );
728
+ var indexes = dt[type + 's']({ search: 'applied' }).indexes();
729
+ var idx1 = indexes.indexOf(last);
730
+ var idx2 = indexes.indexOf(idx);
647
731
 
648
- if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) {
732
+ if (!dt[type + 's']({ selected: true }).any() && idx1 === -1) {
649
733
  // select from top to here - slightly odd, but both Windows and Mac OS
650
734
  // do this
651
- indexes.splice( $.inArray( idx, indexes )+1, indexes.length );
735
+ indexes.splice(indexes.indexOf(idx) + 1, indexes.length);
652
736
  }
653
737
  else {
654
738
  // reverse so we can shift click 'up' as well as down
655
- if ( idx1 > idx2 ) {
739
+ if (idx1 > idx2) {
656
740
  var tmp = idx2;
657
741
  idx2 = idx1;
658
742
  idx1 = tmp;
659
743
  }
660
744
 
661
- indexes.splice( idx2+1, indexes.length );
662
- indexes.splice( 0, idx1 );
745
+ indexes.splice(idx2 + 1, indexes.length);
746
+ indexes.splice(0, idx1);
663
747
  }
664
748
 
665
- if ( ! dt[type]( idx, { selected: true } ).any() ) {
749
+ if (!dt[type](idx, { selected: true }).any()) {
666
750
  // Select range
667
- dt[type+'s']( indexes ).select();
751
+ dt[type + 's'](indexes).select();
668
752
  }
669
753
  else {
670
754
  // Deselect range - need to keep the clicked on row selected
671
- indexes.splice( $.inArray( idx, indexes ), 1 );
672
- dt[type+'s']( indexes ).deselect();
755
+ indexes.splice(indexes.indexOf(idx), 1);
756
+ dt[type + 's'](indexes).deselect();
673
757
  }
674
758
  }
675
759
 
@@ -681,14 +765,13 @@ function rowColumnRange( dt, type, idx, last )
681
765
  * of selection style
682
766
  * @private
683
767
  */
684
- function clear( ctx, force )
685
- {
686
- if ( force || ctx._select.style === 'single' ) {
687
- var api = new DataTable.Api( ctx );
688
-
689
- api.rows( { selected: true } ).deselect();
690
- api.columns( { selected: true } ).deselect();
691
- api.cells( { selected: true } ).deselect();
768
+ function clear(ctx, force) {
769
+ if (force || ctx._select.style === 'single') {
770
+ var api = new DataTable.Api(ctx);
771
+
772
+ api.rows({ selected: true }).deselect();
773
+ api.columns({ selected: true }).deselect();
774
+ api.cells({ selected: true }).deselect();
692
775
  }
693
776
  }
694
777
 
@@ -702,72 +785,74 @@ function clear( ctx, force )
702
785
  * @param {int|object} idx Index of the item to select
703
786
  * @private
704
787
  */
705
- function typeSelect ( e, dt, ctx, type, idx )
706
- {
788
+ function typeSelect(e, dt, ctx, type, idx) {
707
789
  var style = dt.select.style();
708
790
  var toggleable = dt.select.toggleable();
709
- var isSelected = dt[type]( idx, { selected: true } ).any();
710
-
711
- if ( isSelected && ! toggleable ) {
791
+ var isSelected = dt[type](idx, { selected: true }).any();
792
+
793
+ if (isSelected && !toggleable) {
712
794
  return;
713
795
  }
714
796
 
715
- if ( style === 'os' ) {
716
- if ( e.ctrlKey || e.metaKey ) {
797
+ if (style === 'os') {
798
+ if (e.ctrlKey || e.metaKey) {
717
799
  // Add or remove from the selection
718
- dt[type]( idx ).select( ! isSelected );
800
+ dt[type](idx).select(!isSelected);
719
801
  }
720
- else if ( e.shiftKey ) {
721
- if ( type === 'cell' ) {
722
- cellRange( dt, idx, ctx._select_lastCell || null );
802
+ else if (e.shiftKey) {
803
+ if (type === 'cell') {
804
+ cellRange(dt, idx, ctx._select_lastCell || null);
723
805
  }
724
806
  else {
725
- rowColumnRange( dt, type, idx, ctx._select_lastCell ?
726
- ctx._select_lastCell[type] :
727
- null
807
+ rowColumnRange(
808
+ dt,
809
+ type,
810
+ idx,
811
+ ctx._select_lastCell ? ctx._select_lastCell[type] : null
728
812
  );
729
813
  }
730
814
  }
731
815
  else {
732
816
  // No cmd or shift click - deselect if selected, or select
733
817
  // this row only
734
- var selected = dt[type+'s']( { selected: true } );
818
+ var selected = dt[type + 's']({ selected: true });
735
819
 
736
- if ( isSelected && selected.flatten().length === 1 ) {
737
- dt[type]( idx ).deselect();
820
+ if (isSelected && selected.flatten().length === 1) {
821
+ dt[type](idx).deselect();
738
822
  }
739
823
  else {
740
824
  selected.deselect();
741
- dt[type]( idx ).select();
825
+ dt[type](idx).select();
742
826
  }
743
827
  }
744
- } else if ( style == 'multi+shift' ) {
745
- if ( e.shiftKey ) {
746
- if ( type === 'cell' ) {
747
- cellRange( dt, idx, ctx._select_lastCell || null );
828
+ }
829
+ else if (style == 'multi+shift') {
830
+ if (e.shiftKey) {
831
+ if (type === 'cell') {
832
+ cellRange(dt, idx, ctx._select_lastCell || null);
748
833
  }
749
834
  else {
750
- rowColumnRange( dt, type, idx, ctx._select_lastCell ?
751
- ctx._select_lastCell[type] :
752
- null
835
+ rowColumnRange(
836
+ dt,
837
+ type,
838
+ idx,
839
+ ctx._select_lastCell ? ctx._select_lastCell[type] : null
753
840
  );
754
841
  }
755
842
  }
756
843
  else {
757
- dt[ type ]( idx ).select( ! isSelected );
844
+ dt[type](idx).select(!isSelected);
758
845
  }
759
846
  }
760
847
  else {
761
- dt[ type ]( idx ).select( ! isSelected );
848
+ dt[type](idx).select(!isSelected);
762
849
  }
763
850
  }
764
851
 
765
- function _safeId( node ) {
852
+ function _safeId(node) {
766
853
  return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
767
854
  }
768
855
 
769
-
770
-
771
856
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
772
857
  * DataTables selectors
773
858
  */
@@ -775,56 +860,66 @@ function _safeId( node ) {
775
860
  // row and column are basically identical just assigned to different properties
776
861
  // and checking a different array, so we can dynamically create the functions to
777
862
  // reduce the code size
778
- $.each( [
779
- { type: 'row', prop: 'aoData' },
780
- { type: 'column', prop: 'aoColumns' }
781
- ], function ( i, o ) {
782
- DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) {
783
- var selected = opts.selected;
784
- var data;
785
- var out = [];
786
-
787
- if ( selected !== true && selected !== false ) {
788
- return indexes;
789
- }
863
+ $.each(
864
+ [
865
+ { type: 'row', prop: 'aoData' },
866
+ { type: 'column', prop: 'aoColumns' }
867
+ ],
868
+ function (i, o) {
869
+ DataTable.ext.selector[o.type].push(function (settings, opts, indexes) {
870
+ var selected = opts.selected;
871
+ var data;
872
+ var out = [];
873
+
874
+ if (selected !== true && selected !== false) {
875
+ return indexes;
876
+ }
790
877
 
791
- for ( var i=0, ien=indexes.length ; i<ien ; i++ ) {
792
- data = settings[ o.prop ][ indexes[i] ];
878
+ for (var i = 0, ien = indexes.length; i < ien; i++) {
879
+ data = settings[o.prop][indexes[i]];
793
880
 
794
- if ( (selected === true && data._select_selected === true) ||
795
- (selected === false && ! data._select_selected )
796
- ) {
797
- out.push( indexes[i] );
881
+ if (
882
+ data && (
883
+ (selected === true && data._select_selected === true) ||
884
+ (selected === false && !data._select_selected)
885
+ )
886
+ ) {
887
+ out.push(indexes[i]);
888
+ }
798
889
  }
799
- }
800
890
 
801
- return out;
802
- } );
803
- } );
891
+ return out;
892
+ });
893
+ }
894
+ );
804
895
 
805
- DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
896
+ DataTable.ext.selector.cell.push(function (settings, opts, cells) {
806
897
  var selected = opts.selected;
807
898
  var rowData;
808
899
  var out = [];
809
900
 
810
- if ( selected === undefined ) {
901
+ if (selected === undefined) {
811
902
  return cells;
812
903
  }
813
904
 
814
- for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
815
- rowData = settings.aoData[ cells[i].row ];
816
-
817
- if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) ||
818
- (selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) )
905
+ for (var i = 0, ien = cells.length; i < ien; i++) {
906
+ rowData = settings.aoData[cells[i].row];
907
+
908
+ if (
909
+ rowData && (
910
+ (selected === true &&
911
+ rowData._selected_cells &&
912
+ rowData._selected_cells[cells[i].column] === true) ||
913
+ (selected === false &&
914
+ (!rowData._selected_cells || !rowData._selected_cells[cells[i].column]))
915
+ )
819
916
  ) {
820
- out.push( cells[i] );
917
+ out.push(cells[i]);
821
918
  }
822
919
  }
823
920
 
824
921
  return out;
825
- } );
826
-
827
-
922
+ });
828
923
 
829
924
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
830
925
  * DataTables API
@@ -837,67 +932,67 @@ DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
837
932
  var apiRegister = DataTable.Api.register;
838
933
  var apiRegisterPlural = DataTable.Api.registerPlural;
839
934
 
840
- apiRegister( 'select()', function () {
841
- return this.iterator( 'table', function ( ctx ) {
842
- DataTable.select.init( new DataTable.Api( ctx ) );
843
- } );
844
- } );
935
+ apiRegister('select()', function () {
936
+ return this.iterator('table', function (ctx) {
937
+ DataTable.select.init(new DataTable.Api(ctx));
938
+ });
939
+ });
845
940
 
846
- apiRegister( 'select.blurable()', function ( flag ) {
847
- if ( flag === undefined ) {
941
+ apiRegister('select.blurable()', function (flag) {
942
+ if (flag === undefined) {
848
943
  return this.context[0]._select.blurable;
849
944
  }
850
945
 
851
- return this.iterator( 'table', function ( ctx ) {
946
+ return this.iterator('table', function (ctx) {
852
947
  ctx._select.blurable = flag;
853
- } );
854
- } );
948
+ });
949
+ });
855
950
 
856
- apiRegister( 'select.toggleable()', function ( flag ) {
857
- if ( flag === undefined ) {
951
+ apiRegister('select.toggleable()', function (flag) {
952
+ if (flag === undefined) {
858
953
  return this.context[0]._select.toggleable;
859
954
  }
860
955
 
861
- return this.iterator( 'table', function ( ctx ) {
956
+ return this.iterator('table', function (ctx) {
862
957
  ctx._select.toggleable = flag;
863
- } );
864
- } );
958
+ });
959
+ });
865
960
 
866
- apiRegister( 'select.info()', function ( flag ) {
867
- if ( flag === undefined ) {
961
+ apiRegister('select.info()', function (flag) {
962
+ if (flag === undefined) {
868
963
  return this.context[0]._select.info;
869
964
  }
870
965
 
871
- return this.iterator( 'table', function ( ctx ) {
966
+ return this.iterator('table', function (ctx) {
872
967
  ctx._select.info = flag;
873
- } );
874
- } );
968
+ });
969
+ });
875
970
 
876
- apiRegister( 'select.items()', function ( items ) {
877
- if ( items === undefined ) {
971
+ apiRegister('select.items()', function (items) {
972
+ if (items === undefined) {
878
973
  return this.context[0]._select.items;
879
974
  }
880
975
 
881
- return this.iterator( 'table', function ( ctx ) {
976
+ return this.iterator('table', function (ctx) {
882
977
  ctx._select.items = items;
883
978
 
884
- eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] );
885
- } );
886
- } );
979
+ eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
980
+ });
981
+ });
887
982
 
888
983
  // Takes effect from the _next_ selection. None disables future selection, but
889
984
  // does not clear the current selection. Use the `deselect` methods for that
890
- apiRegister( 'select.style()', function ( style ) {
891
- if ( style === undefined ) {
985
+ apiRegister('select.style()', function (style) {
986
+ if (style === undefined) {
892
987
  return this.context[0]._select.style;
893
988
  }
894
989
 
895
- return this.iterator( 'table', function ( ctx ) {
896
- if ( ! ctx._select ) {
897
- DataTable.select.init( new DataTable.Api(ctx) );
990
+ return this.iterator('table', function (ctx) {
991
+ if (!ctx._select) {
992
+ DataTable.select.init(new DataTable.Api(ctx));
898
993
  }
899
994
 
900
- if ( ! ctx._select_init ) {
995
+ if (!ctx._select_init) {
901
996
  init(ctx);
902
997
  }
903
998
 
@@ -905,144 +1000,161 @@ apiRegister( 'select.style()', function ( style ) {
905
1000
 
906
1001
  // Add / remove mouse event handlers. They aren't required when only
907
1002
  // API selection is available
908
- var dt = new DataTable.Api( ctx );
909
- disableMouseSelection( dt );
910
-
911
- if ( style !== 'api' ) {
912
- enableMouseSelection( dt );
1003
+ var dt = new DataTable.Api(ctx);
1004
+ disableMouseSelection(dt);
1005
+
1006
+ if (style !== 'api') {
1007
+ enableMouseSelection(dt);
913
1008
  }
914
1009
 
915
- eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] );
916
- } );
917
- } );
1010
+ eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
1011
+ });
1012
+ });
918
1013
 
919
- apiRegister( 'select.selector()', function ( selector ) {
920
- if ( selector === undefined ) {
1014
+ apiRegister('select.selector()', function (selector) {
1015
+ if (selector === undefined) {
921
1016
  return this.context[0]._select.selector;
922
1017
  }
923
1018
 
924
- return this.iterator( 'table', function ( ctx ) {
925
- disableMouseSelection( new DataTable.Api( ctx ) );
1019
+ return this.iterator('table', function (ctx) {
1020
+ disableMouseSelection(new DataTable.Api(ctx));
926
1021
 
927
1022
  ctx._select.selector = selector;
928
1023
 
929
- if ( ctx._select.style !== 'api' ) {
930
- enableMouseSelection( new DataTable.Api( ctx ) );
1024
+ if (ctx._select.style !== 'api') {
1025
+ enableMouseSelection(new DataTable.Api(ctx));
931
1026
  }
932
- } );
933
- } );
1027
+ });
1028
+ });
934
1029
 
1030
+ apiRegister('select.last()', function (set) {
1031
+ let ctx = this.context[0];
1032
+
1033
+ if (set) {
1034
+ ctx._select_lastCell = set;
1035
+ return this;
1036
+ }
935
1037
 
1038
+ return ctx._select_lastCell;
1039
+ });
936
1040
 
937
- apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) {
1041
+ apiRegisterPlural('rows().select()', 'row().select()', function (select) {
938
1042
  var api = this;
939
1043
 
940
- if ( select === false ) {
1044
+ if (select === false) {
941
1045
  return this.deselect();
942
1046
  }
943
1047
 
944
- this.iterator( 'row', function ( ctx, idx ) {
945
- clear( ctx );
1048
+ this.iterator('row', function (ctx, idx) {
1049
+ clear(ctx);
946
1050
 
947
- ctx.aoData[ idx ]._select_selected = true;
948
- $( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className );
949
- } );
1051
+ // There is a good amount of knowledge of DataTables internals in
1052
+ // this function. It _could_ be done without that, but it would hurt
1053
+ // performance (or DT would need new APIs for this work)
1054
+ var dtData = ctx.aoData[idx];
1055
+ var dtColumns = ctx.aoColumns;
950
1056
 
951
- this.iterator( 'table', function ( ctx, i ) {
952
- eventTrigger( api, 'select', [ 'row', api[i] ], true );
953
- } );
1057
+ $(dtData.nTr).addClass(ctx._select.className);
1058
+ dtData._select_selected = true;
1059
+
1060
+ for (var i=0 ; i<dtColumns.length ; i++) {
1061
+ var col = dtColumns[i];
1062
+
1063
+ if (col.sType === 'select-checkbox') {
1064
+ // Make sure the checkbox shows the right state
1065
+ $('input.dt-select-checkbox', dtData.anCells[i]).prop('checked', true);
1066
+
1067
+ // Invalidate the sort data for this column
1068
+ dtData._aSortData[i] = null;
1069
+ }
1070
+ }
1071
+ });
1072
+
1073
+ this.iterator('table', function (ctx, i) {
1074
+ eventTrigger(api, 'select', ['row', api[i]], true);
1075
+ });
954
1076
 
955
1077
  return this;
956
- } );
1078
+ });
957
1079
 
958
- apiRegister( 'row().selected()', function () {
1080
+ apiRegister('row().selected()', function () {
959
1081
  var ctx = this.context[0];
960
1082
 
961
- if (
962
- ctx &&
963
- this.length &&
964
- ctx.aoData[this[0]] &&
965
- ctx.aoData[this[0]]._select_selected
966
- ) {
1083
+ if (ctx && this.length && ctx.aoData[this[0]] && ctx.aoData[this[0]]._select_selected) {
967
1084
  return true;
968
1085
  }
969
1086
 
970
1087
  return false;
971
- } );
1088
+ });
972
1089
 
973
- apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) {
1090
+ apiRegisterPlural('columns().select()', 'column().select()', function (select) {
974
1091
  var api = this;
975
1092
 
976
- if ( select === false ) {
1093
+ if (select === false) {
977
1094
  return this.deselect();
978
1095
  }
979
1096
 
980
- this.iterator( 'column', function ( ctx, idx ) {
981
- clear( ctx );
1097
+ this.iterator('column', function (ctx, idx) {
1098
+ clear(ctx);
982
1099
 
983
- ctx.aoColumns[ idx ]._select_selected = true;
1100
+ ctx.aoColumns[idx]._select_selected = true;
984
1101
 
985
- var column = new DataTable.Api( ctx ).column( idx );
1102
+ var column = new DataTable.Api(ctx).column(idx);
986
1103
 
987
- $( column.header() ).addClass( ctx._select.className );
988
- $( column.footer() ).addClass( ctx._select.className );
1104
+ $(column.header()).addClass(ctx._select.className);
1105
+ $(column.footer()).addClass(ctx._select.className);
989
1106
 
990
- column.nodes().to$().addClass( ctx._select.className );
991
- } );
1107
+ column.nodes().to$().addClass(ctx._select.className);
1108
+ });
992
1109
 
993
- this.iterator( 'table', function ( ctx, i ) {
994
- eventTrigger( api, 'select', [ 'column', api[i] ], true );
995
- } );
1110
+ this.iterator('table', function (ctx, i) {
1111
+ eventTrigger(api, 'select', ['column', api[i]], true);
1112
+ });
996
1113
 
997
1114
  return this;
998
- } );
1115
+ });
999
1116
 
1000
- apiRegister( 'column().selected()', function () {
1117
+ apiRegister('column().selected()', function () {
1001
1118
  var ctx = this.context[0];
1002
1119
 
1003
- if (
1004
- ctx &&
1005
- this.length &&
1006
- ctx.aoColumns[this[0]] &&
1007
- ctx.aoColumns[this[0]]._select_selected
1008
- ) {
1120
+ if (ctx && this.length && ctx.aoColumns[this[0]] && ctx.aoColumns[this[0]]._select_selected) {
1009
1121
  return true;
1010
1122
  }
1011
1123
 
1012
1124
  return false;
1013
- } );
1125
+ });
1014
1126
 
1015
- apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) {
1127
+ apiRegisterPlural('cells().select()', 'cell().select()', function (select) {
1016
1128
  var api = this;
1017
1129
 
1018
- if ( select === false ) {
1130
+ if (select === false) {
1019
1131
  return this.deselect();
1020
1132
  }
1021
1133
 
1022
- this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
1023
- clear( ctx );
1134
+ this.iterator('cell', function (ctx, rowIdx, colIdx) {
1135
+ clear(ctx);
1024
1136
 
1025
- var data = ctx.aoData[ rowIdx ];
1137
+ var data = ctx.aoData[rowIdx];
1026
1138
 
1027
- if ( data._selected_cells === undefined ) {
1139
+ if (data._selected_cells === undefined) {
1028
1140
  data._selected_cells = [];
1029
1141
  }
1030
1142
 
1031
- data._selected_cells[ colIdx ] = true;
1143
+ data._selected_cells[colIdx] = true;
1032
1144
 
1033
- if ( data.anCells ) {
1034
- $( data.anCells[ colIdx ] ).addClass( ctx._select.className );
1145
+ if (data.anCells) {
1146
+ $(data.anCells[colIdx]).addClass(ctx._select.className);
1035
1147
  }
1036
- } );
1148
+ });
1037
1149
 
1038
- this.iterator( 'table', function ( ctx, i ) {
1039
- eventTrigger( api, 'select', [ 'cell', api.cells(api[i]).indexes().toArray() ], true );
1040
- } );
1150
+ this.iterator('table', function (ctx, i) {
1151
+ eventTrigger(api, 'select', ['cell', api.cells(api[i]).indexes().toArray()], true);
1152
+ });
1041
1153
 
1042
1154
  return this;
1043
- } );
1155
+ });
1044
1156
 
1045
- apiRegister( 'cell().selected()', function () {
1157
+ apiRegister('cell().selected()', function () {
1046
1158
  var ctx = this.context[0];
1047
1159
 
1048
1160
  if (ctx && this.length) {
@@ -1054,110 +1166,125 @@ apiRegister( 'cell().selected()', function () {
1054
1166
  }
1055
1167
 
1056
1168
  return false;
1057
- } );
1058
-
1169
+ });
1059
1170
 
1060
- apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () {
1171
+ apiRegisterPlural('rows().deselect()', 'row().deselect()', function () {
1061
1172
  var api = this;
1062
1173
 
1063
- this.iterator( 'row', function ( ctx, idx ) {
1064
- ctx.aoData[ idx ]._select_selected = false;
1174
+ this.iterator('row', function (ctx, idx) {
1175
+ // Like the select action, this has a lot of knowledge about DT internally
1176
+ var dtData = ctx.aoData[idx];
1177
+ var dtColumns = ctx.aoColumns;
1178
+
1179
+ $(dtData.nTr).removeClass(ctx._select.className);
1180
+ dtData._select_selected = false;
1065
1181
  ctx._select_lastCell = null;
1066
- $( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className );
1067
- } );
1068
1182
 
1069
- this.iterator( 'table', function ( ctx, i ) {
1070
- eventTrigger( api, 'deselect', [ 'row', api[i] ], true );
1071
- } );
1183
+ for (var i=0 ; i<dtColumns.length ; i++) {
1184
+ var col = dtColumns[i];
1185
+
1186
+ if (col.sType === 'select-checkbox') {
1187
+ // Make sure the checkbox shows the right state
1188
+ $('input.dt-select-checkbox', dtData.anCells[i]).prop('checked', false);
1189
+
1190
+ // Invalidate the sort data for this column
1191
+ dtData._aSortData[i] = null;
1192
+ }
1193
+ }
1194
+ });
1195
+
1196
+ this.iterator('table', function (ctx, i) {
1197
+ eventTrigger(api, 'deselect', ['row', api[i]], true);
1198
+ });
1072
1199
 
1073
1200
  return this;
1074
- } );
1201
+ });
1075
1202
 
1076
- apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () {
1203
+ apiRegisterPlural('columns().deselect()', 'column().deselect()', function () {
1077
1204
  var api = this;
1078
1205
 
1079
- this.iterator( 'column', function ( ctx, idx ) {
1080
- ctx.aoColumns[ idx ]._select_selected = false;
1206
+ this.iterator('column', function (ctx, idx) {
1207
+ ctx.aoColumns[idx]._select_selected = false;
1081
1208
 
1082
- var api = new DataTable.Api( ctx );
1083
- var column = api.column( idx );
1209
+ var api = new DataTable.Api(ctx);
1210
+ var column = api.column(idx);
1084
1211
 
1085
- $( column.header() ).removeClass( ctx._select.className );
1086
- $( column.footer() ).removeClass( ctx._select.className );
1212
+ $(column.header()).removeClass(ctx._select.className);
1213
+ $(column.footer()).removeClass(ctx._select.className);
1087
1214
 
1088
1215
  // Need to loop over each cell, rather than just using
1089
1216
  // `column().nodes()` as cells which are individually selected should
1090
1217
  // not have the `selected` class removed from them
1091
- api.cells( null, idx ).indexes().each( function (cellIdx) {
1092
- var data = ctx.aoData[ cellIdx.row ];
1093
- var cellSelected = data._selected_cells;
1094
-
1095
- if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) {
1096
- $( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className );
1097
- }
1098
- } );
1099
- } );
1218
+ api.cells(null, idx)
1219
+ .indexes()
1220
+ .each(function (cellIdx) {
1221
+ var data = ctx.aoData[cellIdx.row];
1222
+ var cellSelected = data._selected_cells;
1223
+
1224
+ if (data.anCells && (!cellSelected || !cellSelected[cellIdx.column])) {
1225
+ $(data.anCells[cellIdx.column]).removeClass(ctx._select.className);
1226
+ }
1227
+ });
1228
+ });
1100
1229
 
1101
- this.iterator( 'table', function ( ctx, i ) {
1102
- eventTrigger( api, 'deselect', [ 'column', api[i] ], true );
1103
- } );
1230
+ this.iterator('table', function (ctx, i) {
1231
+ eventTrigger(api, 'deselect', ['column', api[i]], true);
1232
+ });
1104
1233
 
1105
1234
  return this;
1106
- } );
1235
+ });
1107
1236
 
1108
- apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () {
1237
+ apiRegisterPlural('cells().deselect()', 'cell().deselect()', function () {
1109
1238
  var api = this;
1110
1239
 
1111
- this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
1112
- var data = ctx.aoData[ rowIdx ];
1240
+ this.iterator('cell', function (ctx, rowIdx, colIdx) {
1241
+ var data = ctx.aoData[rowIdx];
1113
1242
 
1114
- if(data._selected_cells !== undefined) {
1115
- data._selected_cells[ colIdx ] = false;
1243
+ if (data._selected_cells !== undefined) {
1244
+ data._selected_cells[colIdx] = false;
1116
1245
  }
1117
1246
 
1118
1247
  // Remove class only if the cells exist, and the cell is not column
1119
1248
  // selected, in which case the class should remain (since it is selected
1120
1249
  // in the column)
1121
- if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) {
1122
- $( data.anCells[ colIdx ] ).removeClass( ctx._select.className );
1250
+ if (data.anCells && !ctx.aoColumns[colIdx]._select_selected) {
1251
+ $(data.anCells[colIdx]).removeClass(ctx._select.className);
1123
1252
  }
1124
- } );
1253
+ });
1125
1254
 
1126
- this.iterator( 'table', function ( ctx, i ) {
1127
- eventTrigger( api, 'deselect', [ 'cell', api[i] ], true );
1128
- } );
1255
+ this.iterator('table', function (ctx, i) {
1256
+ eventTrigger(api, 'deselect', ['cell', api[i]], true);
1257
+ });
1129
1258
 
1130
1259
  return this;
1131
- } );
1132
-
1133
-
1260
+ });
1134
1261
 
1135
1262
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1136
1263
  * Buttons
1137
1264
  */
1138
- function i18n( label, def ) {
1265
+ function i18n(label, def) {
1139
1266
  return function (dt) {
1140
- return dt.i18n( 'buttons.'+label, def );
1267
+ return dt.i18n('buttons.' + label, def);
1141
1268
  };
1142
1269
  }
1143
1270
 
1144
1271
  // Common events with suitable namespaces
1145
- function namespacedEvents ( config ) {
1272
+ function namespacedEvents(config) {
1146
1273
  var unique = config._eventNamespace;
1147
1274
 
1148
- return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
1275
+ return 'draw.dt.DT' + unique + ' select.dt.DT' + unique + ' deselect.dt.DT' + unique;
1149
1276
  }
1150
1277
 
1151
- function enabled ( dt, config ) {
1152
- if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) {
1278
+ function enabled(dt, config) {
1279
+ if (config.limitTo.indexOf('rows') !== -1 && dt.rows({ selected: true }).any()) {
1153
1280
  return true;
1154
1281
  }
1155
1282
 
1156
- if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) {
1283
+ if (config.limitTo.indexOf('columns') !== -1 && dt.columns({ selected: true }).any()) {
1157
1284
  return true;
1158
1285
  }
1159
1286
 
1160
- if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) {
1287
+ if (config.limitTo.indexOf('cells') !== -1 && dt.cells({ selected: true }).any()) {
1161
1288
  return true;
1162
1289
  }
1163
1290
 
@@ -1166,111 +1293,114 @@ function enabled ( dt, config ) {
1166
1293
 
1167
1294
  var _buttonNamespace = 0;
1168
1295
 
1169
- $.extend( DataTable.ext.buttons, {
1296
+ $.extend(DataTable.ext.buttons, {
1170
1297
  selected: {
1171
- text: i18n( 'selected', 'Selected' ),
1298
+ text: i18n('selected', 'Selected'),
1172
1299
  className: 'buttons-selected',
1173
- limitTo: [ 'rows', 'columns', 'cells' ],
1174
- init: function ( dt, node, config ) {
1300
+ limitTo: ['rows', 'columns', 'cells'],
1301
+ init: function (dt, node, config) {
1175
1302
  var that = this;
1176
- config._eventNamespace = '.select'+(_buttonNamespace++);
1303
+ config._eventNamespace = '.select' + _buttonNamespace++;
1177
1304
 
1178
1305
  // .DT namespace listeners are removed by DataTables automatically
1179
1306
  // on table destroy
1180
- dt.on( namespacedEvents(config), function () {
1181
- that.enable( enabled(dt, config) );
1182
- } );
1307
+ dt.on(namespacedEvents(config), function () {
1308
+ that.enable(enabled(dt, config));
1309
+ });
1183
1310
 
1184
1311
  this.disable();
1185
1312
  },
1186
- destroy: function ( dt, node, config ) {
1187
- dt.off( config._eventNamespace );
1313
+ destroy: function (dt, node, config) {
1314
+ dt.off(config._eventNamespace);
1188
1315
  }
1189
1316
  },
1190
1317
  selectedSingle: {
1191
- text: i18n( 'selectedSingle', 'Selected single' ),
1318
+ text: i18n('selectedSingle', 'Selected single'),
1192
1319
  className: 'buttons-selected-single',
1193
- init: function ( dt, node, config ) {
1320
+ init: function (dt, node, config) {
1194
1321
  var that = this;
1195
- config._eventNamespace = '.select'+(_buttonNamespace++);
1322
+ config._eventNamespace = '.select' + _buttonNamespace++;
1196
1323
 
1197
- dt.on( namespacedEvents(config), function () {
1198
- var count = dt.rows( { selected: true } ).flatten().length +
1199
- dt.columns( { selected: true } ).flatten().length +
1200
- dt.cells( { selected: true } ).flatten().length;
1324
+ dt.on(namespacedEvents(config), function () {
1325
+ var count =
1326
+ dt.rows({ selected: true }).flatten().length +
1327
+ dt.columns({ selected: true }).flatten().length +
1328
+ dt.cells({ selected: true }).flatten().length;
1201
1329
 
1202
- that.enable( count === 1 );
1203
- } );
1330
+ that.enable(count === 1);
1331
+ });
1204
1332
 
1205
1333
  this.disable();
1206
1334
  },
1207
- destroy: function ( dt, node, config ) {
1208
- dt.off( config._eventNamespace );
1335
+ destroy: function (dt, node, config) {
1336
+ dt.off(config._eventNamespace);
1209
1337
  }
1210
1338
  },
1211
1339
  selectAll: {
1212
- text: i18n( 'selectAll', 'Select all' ),
1340
+ text: i18n('selectAll', 'Select all'),
1213
1341
  className: 'buttons-select-all',
1214
- action: function () {
1342
+ action: function (e, dt, node, config) {
1215
1343
  var items = this.select.items();
1216
- this[ items+'s' ]().select();
1344
+ var mod = config.selectorModifier;
1345
+
1346
+ if (mod) {
1347
+ if (typeof mod === 'function') {
1348
+ mod = mod.call(dt, e, dt, node, config);
1349
+ }
1350
+
1351
+ this[items + 's'](mod).select();
1352
+ }
1353
+ else {
1354
+ this[items + 's']().select();
1355
+ }
1217
1356
  }
1357
+ // selectorModifier can be specified
1218
1358
  },
1219
1359
  selectNone: {
1220
- text: i18n( 'selectNone', 'Deselect all' ),
1360
+ text: i18n('selectNone', 'Deselect all'),
1221
1361
  className: 'buttons-select-none',
1222
1362
  action: function () {
1223
- clear( this.settings()[0], true );
1363
+ clear(this.settings()[0], true);
1224
1364
  },
1225
- init: function ( dt, node, config ) {
1365
+ init: function (dt, node, config) {
1226
1366
  var that = this;
1227
- config._eventNamespace = '.select'+(_buttonNamespace++);
1367
+ config._eventNamespace = '.select' + _buttonNamespace++;
1228
1368
 
1229
- dt.on( namespacedEvents(config), function () {
1230
- var count = dt.rows( { selected: true } ).flatten().length +
1231
- dt.columns( { selected: true } ).flatten().length +
1232
- dt.cells( { selected: true } ).flatten().length;
1369
+ dt.on(namespacedEvents(config), function () {
1370
+ var count =
1371
+ dt.rows({ selected: true }).flatten().length +
1372
+ dt.columns({ selected: true }).flatten().length +
1373
+ dt.cells({ selected: true }).flatten().length;
1233
1374
 
1234
- that.enable( count > 0 );
1235
- } );
1375
+ that.enable(count > 0);
1376
+ });
1236
1377
 
1237
1378
  this.disable();
1238
1379
  },
1239
- destroy: function ( dt, node, config ) {
1240
- dt.off( config._eventNamespace );
1380
+ destroy: function (dt, node, config) {
1381
+ dt.off(config._eventNamespace);
1241
1382
  }
1242
1383
  },
1243
1384
  showSelected: {
1244
- text: i18n( 'showSelected', 'Show only selected' ),
1385
+ text: i18n('showSelected', 'Show only selected'),
1245
1386
  className: 'buttons-show-selected',
1246
- action: function (e, dt, node, conf) {
1247
- // Works by having a filtering function which will reduce to the selected
1248
- // items only. So we can re-reference the function it gets stored in the
1249
- // `conf` object
1250
- if (conf._filter) {
1251
- var idx = DataTable.ext.search.indexOf(conf._filter);
1252
-
1253
- if (idx !== -1) {
1254
- DataTable.ext.search.splice(idx, 1);
1255
- conf._filter = null;
1256
- }
1387
+ action: function (e, dt) {
1388
+ if (dt.search.fixed('dt-select')) {
1389
+ // Remove existing function
1390
+ dt.search.fixed('dt-select', null);
1257
1391
 
1258
1392
  this.active(false);
1259
1393
  }
1260
1394
  else {
1261
- var fn = function (s, data, idx) {
1262
- // Need to be sure we are operating on our table!
1263
- if (s !== dt.settings()[0]) {
1264
- return true;
1265
- }
1266
-
1267
- let row = s.aoData[idx];
1268
-
1269
- return row._select_selected;
1270
- }
1395
+ // Use a fixed filtering function to match on selected rows
1396
+ // This needs to reference the internal aoData since that is
1397
+ // where Select stores its reference for the selected state
1398
+ var dataSrc = dt.settings()[0].aoData;
1271
1399
 
1272
- conf._filter = fn;
1273
- DataTable.ext.search.push(fn);
1400
+ dt.search.fixed('dt-select', function (text, data, idx) {
1401
+ // _select_selected is set by Select on the data object for the row
1402
+ return dataSrc[idx]._select_selected;
1403
+ });
1274
1404
 
1275
1405
  this.active(true);
1276
1406
  }
@@ -1278,27 +1408,94 @@ $.extend( DataTable.ext.buttons, {
1278
1408
  dt.draw();
1279
1409
  }
1280
1410
  }
1281
- } );
1411
+ });
1282
1412
 
1283
- $.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) {
1413
+ $.each(['Row', 'Column', 'Cell'], function (i, item) {
1284
1414
  var lc = item.toLowerCase();
1285
1415
 
1286
- DataTable.ext.buttons[ 'select'+item+'s' ] = {
1287
- text: i18n( 'select'+item+'s', 'Select '+lc+'s' ),
1288
- className: 'buttons-select-'+lc+'s',
1416
+ DataTable.ext.buttons['select' + item + 's'] = {
1417
+ text: i18n('select' + item + 's', 'Select ' + lc + 's'),
1418
+ className: 'buttons-select-' + lc + 's',
1289
1419
  action: function () {
1290
- this.select.items( lc );
1420
+ this.select.items(lc);
1291
1421
  },
1292
- init: function ( dt ) {
1422
+ init: function (dt) {
1293
1423
  var that = this;
1294
1424
 
1295
- dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) {
1296
- that.active( items === lc );
1297
- } );
1425
+ dt.on('selectItems.dt.DT', function (e, ctx, items) {
1426
+ that.active(items === lc);
1427
+ });
1298
1428
  }
1299
1429
  };
1300
- } );
1430
+ });
1431
+
1432
+ DataTable.type('select-checkbox', {
1433
+ className: 'dt-select',
1434
+ detect: function (data) {
1435
+ // Rendering function will tell us if it is a checkbox type
1436
+ return data === 'select-checkbox' ? data : false;
1437
+ },
1438
+ order: {
1439
+ pre: function (d) {
1440
+ return d === 'X' ? -1 : 0;
1441
+ }
1442
+ }
1443
+ });
1301
1444
 
1445
+ $.extend(true, DataTable.defaults.oLanguage, {
1446
+ select: {
1447
+ aria: {
1448
+ rowCheckbox: 'Select row'
1449
+ }
1450
+ }
1451
+ });
1452
+
1453
+ DataTable.render.select = function (valueProp, nameProp) {
1454
+ var valueFn = valueProp ? DataTable.util.get(valueProp) : null;
1455
+ var nameFn = nameProp ? DataTable.util.get(nameProp) : null;
1456
+
1457
+ return function (data, type, row, meta) {
1458
+ var dtRow = meta.settings.aoData[meta.row];
1459
+ var selected = dtRow._select_selected;
1460
+ var ariaLabel = meta.settings.oLanguage.select.aria.rowCheckbox;
1461
+
1462
+ if (type === 'display') {
1463
+ return $('<input>')
1464
+ .attr({
1465
+ 'aria-label': ariaLabel,
1466
+ class: 'dt-select-checkbox',
1467
+ name: nameFn ? nameFn(row) : null,
1468
+ type: 'checkbox',
1469
+ value: valueFn ? valueFn(row) : null,
1470
+ checked: selected
1471
+ })[0];
1472
+ }
1473
+ else if (type === 'type') {
1474
+ return 'select-checkbox';
1475
+ }
1476
+ else if (type === 'filter') {
1477
+ return '';
1478
+ }
1479
+
1480
+ return selected ? 'X' : '';
1481
+ }
1482
+ }
1483
+
1484
+ // Legacy checkbox ordering
1485
+ DataTable.ext.order['select-checkbox'] = function (settings, col) {
1486
+ return this.api()
1487
+ .column(col, { order: 'index' })
1488
+ .nodes()
1489
+ .map(function (td) {
1490
+ if (settings._select.items === 'row') {
1491
+ return $(td).parent().hasClass(settings._select.className);
1492
+ }
1493
+ else if (settings._select.items === 'cell') {
1494
+ return $(td).hasClass(settings._select.className);
1495
+ }
1496
+ return false;
1497
+ });
1498
+ };
1302
1499
 
1303
1500
  $.fn.DataTable.select = DataTable.select;
1304
1501
 
@@ -1310,13 +1507,13 @@ $.fn.DataTable.select = DataTable.select;
1310
1507
  // this required that the table be in the document! If it isn't then something
1311
1508
  // needs to trigger this method unfortunately. The next major release of
1312
1509
  // DataTables will rework the events and address this.
1313
- $(document).on( 'preInit.dt.dtSelect', function (e, ctx) {
1314
- if ( e.namespace !== 'dt' ) {
1510
+ $(document).on('preInit.dt.dtSelect', function (e, ctx) {
1511
+ if (e.namespace !== 'dt') {
1315
1512
  return;
1316
1513
  }
1317
1514
 
1318
- DataTable.select.init( new DataTable.Api( ctx ) );
1319
- } );
1515
+ DataTable.select.init(new DataTable.Api(ctx));
1516
+ });
1320
1517
 
1321
1518
 
1322
1519
  export default DataTable;