25
if ( typeof define === 'function' && define.amd ) {
27
define( ['jquery', 'datatables.net'], function ( $ ) {
28
return factory( $, window, document );
31
else if ( typeof exports === 'object' ) {
33
module.exports = function (root, $) {
38
if ( ! $ || ! $.fn.dataTable ) {
39
$ = require('datatables.net')(root, $).$;
42
return factory( $, root, root.document );
47
factory( jQuery, window, document );
49
}(function( $, window, document, undefined ) {
51
var DataTable = $.fn.dataTable;
57
DataTable.select.version = '1.3.4-dev';
59
DataTable.select.init = function ( dt ) {
60
var ctx = dt.settings()[0];
66
var savedSelected = dt.state.loaded();
68
var selectAndSave = function(e, settings, data) {
69
if(data === null || data.select === undefined) {
73
dt.columns().deselect();
74
dt.cells().deselect();
75
if (data.select.rows !== undefined) {
76
dt.rows(data.select.rows).select();
78
if (data.select.columns !== undefined) {
79
dt.columns(data.select.columns).select();
81
if (data.select.cells !== undefined) {
82
for(var i = 0; i < data.select.cells.length; i++) {
83
dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
89
dt.one('init', function() {
90
dt.on('stateSaveParams', function(e, settings, data) {
92
data.select.rows = dt.rows({selected:true}).ids(true).toArray();
93
data.select.columns = dt.columns({selected:true})[0];
94
data.select.cells = dt.cells({selected:true})[0].map(function(coords) {
95
return {row: dt.row(coords.row).id(true), column: coords.column}
99
selectAndSave(undefined, undefined, savedSelected)
100
dt.on('stateLoaded stateLoadParams', selectAndSave)
103
var init = ctx.oInit.select;
104
var defaults = DataTable.defaults.select;
105
var opts = init === undefined ?
112
var blurable = false;
113
var toggleable = true;
115
var selector = 'td, th';
116
var className = 'selected';
117
var setStyle = false;
122
if ( opts === true ) {
126
else if ( typeof opts === 'string' ) {
130
else if ( $.isPlainObject( opts ) ) {
131
if ( opts.blurable !== undefined ) {
132
blurable = opts.blurable;
135
if ( opts.toggleable !== undefined ) {
136
toggleable = opts.toggleable;
139
if ( opts.info !== undefined ) {
143
if ( opts.items !== undefined ) {
147
if ( opts.style !== undefined ) {
156
if ( opts.selector !== undefined ) {
157
selector = opts.selector;
160
if ( opts.className !== undefined ) {
161
className = opts.className;
165
dt.select.selector( selector );
166
dt.select.items( items );
167
dt.select.style( style );
168
dt.select.blurable( blurable );
169
dt.select.toggleable( toggleable );
170
dt.select.info( info );
171
ctx._select.className = className;
175
$.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) {
176
return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) {
177
if ( settings._select.items === 'row' ) {
178
return $( td ).parent().hasClass( settings._select.className );
179
} else if ( settings._select.items === 'cell' ) {
180
return $( td ).hasClass( settings._select.className );
188
if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
189
dt.select.style( 'os' );
276
function cellRange( dt, idx, last )
281
var selectColumns = function ( start, end ) {
289
return dt.columns( ':visible' ).indexes().filter( function (i) {
303
var selectRows = function ( start, end ) {
304
var indexes = dt.rows( { search: 'applied' } ).indexes();
307
if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) {
314
return indexes.filter( function (i) {
328
if ( ! dt.cells( { selected: true } ).any() && ! last ) {
330
columnIndexes = selectColumns( 0, idx.column );
331
rowIndexes = selectRows( 0 , idx.row );
335
columnIndexes = selectColumns( last.column, idx.column );
336
rowIndexes = selectRows( last.row , idx.row );
339
indexes = dt.cells( rowIndexes, columnIndexes ).flatten();
341
if ( ! dt.cells( idx, { selected: true } ).any() ) {
343
dt.cells( indexes ).select();
347
dt.cells( indexes ).deselect();
357
function disableMouseSelection( dt )
359
var ctx = dt.settings()[0];
360
var selector = ctx._select.selector;
362
$( dt.table().container() )
363
.off( 'mousedown.dtSelect', selector )
364
.off( 'mouseup.dtSelect', selector )
365
.off( 'click.dtSelect', selector );
367
$('body').off( 'click.dtSelect' + _safeId(dt.table().node()) );
376
function enableMouseSelection ( dt )
378
var container = $( dt.table().container() );
379
var ctx = dt.settings()[0];
380
var selector = ctx._select.selector;
384
.on( 'mousedown.dtSelect', selector, function(e) {
387
if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
389
.css( '-moz-user-select', 'none' )
390
.one('selectstart.dtSelect', selector, function () {
395
if ( window.getSelection ) {
396
matchSelection = window.getSelection();
399
.on( 'mouseup.dtSelect', selector, function() {
402
container.css( '-moz-user-select', '' );
404
.on( 'click.dtSelect', selector, function ( e ) {
405
var items = dt.select.items();
410
if ( matchSelection ) {
411
var selection = window.getSelection();
415
if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) {
416
if ( selection !== matchSelection ) {
422
var ctx = dt.settings()[0];
423
var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.');
426
if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) {
430
var cell = dt.cell( $(e.target).closest('td, th') );
434
if ( ! cell.any() ) {
438
var event = $.Event('user-select.dt');
439
eventTrigger( dt, event, [ items, cell, e ] );
441
if ( event.isDefaultPrevented() ) {
445
var cellIndex = cell.index();
446
if ( items === 'row' ) {
448
typeSelect( e, dt, ctx, 'row', idx );
450
else if ( items === 'column' ) {
451
idx = cell.index().column;
452
typeSelect( e, dt, ctx, 'column', idx );
454
else if ( items === 'cell' ) {
456
typeSelect( e, dt, ctx, 'cell', idx );
459
ctx._select_lastCell = cellIndex;
463
$('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) {
464
if ( ctx._select.blurable ) {
466
if ( $(e.target).parents().filter( dt.table().container() ).length ) {
472
if ( $(e.target).parents('html').length === 0 ) {
477
if ( $(e.target).parents('div.DTE').length ) {
496
function eventTrigger ( api, type, args, any )
498
if ( any && ! api.flatten().length ) {
502
if ( typeof type === 'string' ) {
508
$(api.table().node()).trigger( type, args );
520
var ctx = api.settings()[0];
522
if ( ! ctx._select.info || ! ctx.aanFeatures.i ) {
526
if ( api.select.style() === 'api' ) {
530
var rows = api.rows( { selected: true } ).flatten().length;
531
var columns = api.columns( { selected: true } ).flatten().length;
532
var cells = api.cells( { selected: true } ).flatten().length;
534
var add = function ( el, name, num ) {
535
el.append( $('<span class="select-item"/>').append( api.i18n(
537
{ _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' },
543
$.each( ctx.aanFeatures.i, function ( i, el ) {
546
var output = $('<span class="select-info"/>');
547
add( output, 'row', rows );
548
add( output, 'column', columns );
549
add( output, 'cell', cells );
551
var exisiting = el.children('span.select-info');
552
if ( exisiting.length ) {
556
if ( output.text() !== '' ) {
572
function init ( ctx ) {
573
var api = new DataTable.Api( ctx );
574
ctx._select_init = true;
583
ctx.aoRowCreatedCallback.push( {
584
fn: function ( row, data, index ) {
586
var d = ctx.aoData[ index ];
589
if ( d._select_selected ) {
590
$( row ).addClass( ctx._select.className );
595
for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) {
596
if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) {
597
$(d.anCells[i]).addClass( ctx._select.className );
601
sName: 'select-deferRender'
606
api.on( 'preXhr.dt.dtSelect', function (e, settings) {
607
if (settings !== api.settings()[0]) {
614
var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) {
615
return d !== undefined;
618
var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) {
619
var id = api.row( cellIdx.row ).id( true );
621
{ row: id, column: cellIdx.column } :
623
} ).filter( function ( d ) {
624
return d !== undefined;
628
api.one( 'draw.dt.dtSelect', function () {
629
api.rows( rows ).select();
633
cells.each( function ( id ) {
634
api.cells( id.row, id.column ).select();
641
api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
647
api.on( 'destroy.dtSelect', function () {
648
api.rows({selected: true}).deselect();
650
disableMouseSelection( api );
651
api.off( '.dtSelect' );
652
$('body').off('.dtSelect' + _safeId(api.table().node()));
666
function rowColumnRange( dt, type, idx, last )
669
var indexes = dt[type+'s']( { search: 'applied' } ).indexes();
670
var idx1 = $.inArray( last, indexes );
671
var idx2 = $.inArray( idx, indexes );
673
if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) {
676
indexes.splice( $.inArray( idx, indexes )+1, indexes.length );
686
indexes.splice( idx2+1, indexes.length );
687
indexes.splice( 0, idx1 );
690
if ( ! dt[type]( idx, { selected: true } ).any() ) {
692
dt[type+'s']( indexes ).select();
696
indexes.splice( $.inArray( idx, indexes ), 1 );
697
dt[type+'s']( indexes ).deselect();
709
function clear( ctx, force )
711
if ( force || ctx._select.style === 'single' ) {
712
var api = new DataTable.Api( ctx );
714
api.rows( { selected: true } ).deselect();
715
api.columns( { selected: true } ).deselect();
716
api.cells( { selected: true } ).deselect();
730
function typeSelect ( e, dt, ctx, type, idx )
732
var style = dt.select.style();
733
var toggleable = dt.select.toggleable();
734
var isSelected = dt[type]( idx, { selected: true } ).any();
736
if ( isSelected && ! toggleable ) {
740
if ( style === 'os' ) {
741
if ( e.ctrlKey || e.metaKey ) {
743
dt[type]( idx ).select( ! isSelected );
745
else if ( e.shiftKey ) {
746
if ( type === 'cell' ) {
747
cellRange( dt, idx, ctx._select_lastCell || null );
750
rowColumnRange( dt, type, idx, ctx._select_lastCell ?
751
ctx._select_lastCell[type] :
759
var selected = dt[type+'s']( { selected: true } );
761
if ( isSelected && selected.flatten().length === 1 ) {
762
dt[type]( idx ).deselect();
766
dt[type]( idx ).select();
769
} else if ( style == 'multi+shift' ) {
771
if ( type === 'cell' ) {
772
cellRange( dt, idx, ctx._select_lastCell || null );
775
rowColumnRange( dt, type, idx, ctx._select_lastCell ?
776
ctx._select_lastCell[type] :
782
dt[ type ]( idx ).select( ! isSelected );
786
dt[ type ]( idx ).select( ! isSelected );
790
function _safeId( node ) {
791
return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
804
{ type: 'row', prop: 'aoData' },
805
{ type: 'column', prop: 'aoColumns' }
806
], function ( i, o ) {
807
DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) {
808
var selected = opts.selected;
812
if ( selected !== true && selected !== false ) {
816
for ( var i=0, ien=indexes.length ; i<ien ; i++ ) {
817
data = settings[ o.prop ][ indexes[i] ];
819
if ( (selected === true && data._select_selected === true) ||
820
(selected === false && ! data._select_selected )
822
out.push( indexes[i] );
830
DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
831
var selected = opts.selected;
835
if ( selected === undefined ) {
839
for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
840
rowData = settings.aoData[ cells[i].row ];
842
if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) ||
843
(selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) )
845
out.push( cells[i] );
862
var apiRegister = DataTable.Api.register;
863
var apiRegisterPlural = DataTable.Api.registerPlural;
865
apiRegister( 'select()', function () {
866
return this.iterator( 'table', function ( ctx ) {
867
DataTable.select.init( new DataTable.Api( ctx ) );
871
apiRegister( 'select.blurable()', function ( flag ) {
872
if ( flag === undefined ) {
873
return this.context[0]._select.blurable;
876
return this.iterator( 'table', function ( ctx ) {
877
ctx._select.blurable = flag;
881
apiRegister( 'select.toggleable()', function ( flag ) {
882
if ( flag === undefined ) {
883
return this.context[0]._select.toggleable;
886
return this.iterator( 'table', function ( ctx ) {
887
ctx._select.toggleable = flag;
891
apiRegister( 'select.info()', function ( flag ) {
892
if ( flag === undefined ) {
893
return this.context[0]._select.info;
896
return this.iterator( 'table', function ( ctx ) {
897
ctx._select.info = flag;
901
apiRegister( 'select.items()', function ( items ) {
902
if ( items === undefined ) {
903
return this.context[0]._select.items;
906
return this.iterator( 'table', function ( ctx ) {
907
ctx._select.items = items;
909
eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] );
915
apiRegister( 'select.style()', function ( style ) {
916
if ( style === undefined ) {
917
return this.context[0]._select.style;
920
return this.iterator( 'table', function ( ctx ) {
921
if ( ! ctx._select ) {
922
DataTable.select.init( new DataTable.Api(ctx) );
925
if ( ! ctx._select_init ) {
929
ctx._select.style = style;
933
var dt = new DataTable.Api( ctx );
934
disableMouseSelection( dt );
936
if ( style !== 'api' ) {
937
enableMouseSelection( dt );
940
eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] );
944
apiRegister( 'select.selector()', function ( selector ) {
945
if ( selector === undefined ) {
946
return this.context[0]._select.selector;
949
return this.iterator( 'table', function ( ctx ) {
950
disableMouseSelection( new DataTable.Api( ctx ) );
952
ctx._select.selector = selector;
954
if ( ctx._select.style !== 'api' ) {
955
enableMouseSelection( new DataTable.Api( ctx ) );
962
apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) {
965
if ( select === false ) {
966
return this.deselect();
969
this.iterator( 'row', function ( ctx, idx ) {
972
ctx.aoData[ idx ]._select_selected = true;
973
$( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className );
976
this.iterator( 'table', function ( ctx, i ) {
977
eventTrigger( api, 'select', [ 'row', api[i] ], true );
983
apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) {
986
if ( select === false ) {
987
return this.deselect();
990
this.iterator( 'column', function ( ctx, idx ) {
993
ctx.aoColumns[ idx ]._select_selected = true;
995
var column = new DataTable.Api( ctx ).column( idx );
997
$( column.header() ).addClass( ctx._select.className );
998
$( column.footer() ).addClass( ctx._select.className );
1000
column.nodes().to$().addClass( ctx._select.className );
1003
this.iterator( 'table', function ( ctx, i ) {
1004
eventTrigger( api, 'select', [ 'column', api[i] ], true );
1010
apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) {
1013
if ( select === false ) {
1014
return this.deselect();
1017
this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
1020
var data = ctx.aoData[ rowIdx ];
1022
if ( data._selected_cells === undefined ) {
1023
data._selected_cells = [];
1026
data._selected_cells[ colIdx ] = true;
1028
if ( data.anCells ) {
1029
$( data.anCells[ colIdx ] ).addClass( ctx._select.className );
1033
this.iterator( 'table', function ( ctx, i ) {
1034
eventTrigger( api, 'select', [ 'cell', api.cells(api[i]).indexes().toArray() ], true );
1041
apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () {
1044
this.iterator( 'row', function ( ctx, idx ) {
1045
ctx.aoData[ idx ]._select_selected = false;
1046
ctx._select_lastCell = null;
1047
$( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className );
1050
this.iterator( 'table', function ( ctx, i ) {
1051
eventTrigger( api, 'deselect', [ 'row', api[i] ], true );
1057
apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () {
1060
this.iterator( 'column', function ( ctx, idx ) {
1061
ctx.aoColumns[ idx ]._select_selected = false;
1063
var api = new DataTable.Api( ctx );
1064
var column = api.column( idx );
1066
$( column.header() ).removeClass( ctx._select.className );
1067
$( column.footer() ).removeClass( ctx._select.className );
1072
api.cells( null, idx ).indexes().each( function (cellIdx) {
1073
var data = ctx.aoData[ cellIdx.row ];
1074
var cellSelected = data._selected_cells;
1076
if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) {
1077
$( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className );
1082
this.iterator( 'table', function ( ctx, i ) {
1083
eventTrigger( api, 'deselect', [ 'column', api[i] ], true );
1089
apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () {
1092
this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
1093
var data = ctx.aoData[ rowIdx ];
1095
if(data._selected_cells !== undefined) {
1096
data._selected_cells[ colIdx ] = false;
1102
if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) {
1103
$( data.anCells[ colIdx ] ).removeClass( ctx._select.className );
1107
this.iterator( 'table', function ( ctx, i ) {
1108
eventTrigger( api, 'deselect', [ 'cell', api[i] ], true );
1119
function i18n( label, def ) {
1120
return function (dt) {
1121
return dt.i18n( 'buttons.'+label, def );
1126
function namespacedEvents ( config ) {
1127
var unique = config._eventNamespace;
1129
return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
1132
function enabled ( dt, config ) {
1133
if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) {
1137
if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) {
1141
if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) {
1148
var _buttonNamespace = 0;
1150
$.extend( DataTable.ext.buttons, {
1152
text: i18n( 'selected', 'Selected' ),
1153
className: 'buttons-selected',
1154
limitTo: [ 'rows', 'columns', 'cells' ],
1155
init: function ( dt, node, config ) {
1157
config._eventNamespace = '.select'+(_buttonNamespace++);
1161
dt.on( namespacedEvents(config), function () {
1162
that.enable( enabled(dt, config) );
1167
destroy: function ( dt, node, config ) {
1168
dt.off( config._eventNamespace );
1172
text: i18n( 'selectedSingle', 'Selected single' ),
1173
className: 'buttons-selected-single',
1174
init: function ( dt, node, config ) {
1176
config._eventNamespace = '.select'+(_buttonNamespace++);
1178
dt.on( namespacedEvents(config), function () {
1179
var count = dt.rows( { selected: true } ).flatten().length +
1180
dt.columns( { selected: true } ).flatten().length +
1181
dt.cells( { selected: true } ).flatten().length;
1183
that.enable( count === 1 );
1188
destroy: function ( dt, node, config ) {
1189
dt.off( config._eventNamespace );
1193
text: i18n( 'selectAll', 'Select all' ),
1194
className: 'buttons-select-all',
1195
action: function () {
1196
var items = this.select.items();
1197
this[ items+'s' ]().select();
1201
text: i18n( 'selectNone', 'Deselect all' ),
1202
className: 'buttons-select-none',
1203
action: function () {
1204
clear( this.settings()[0], true );
1206
init: function ( dt, node, config ) {
1208
config._eventNamespace = '.select'+(_buttonNamespace++);
1210
dt.on( namespacedEvents(config), function () {
1211
var count = dt.rows( { selected: true } ).flatten().length +
1212
dt.columns( { selected: true } ).flatten().length +
1213
dt.cells( { selected: true } ).flatten().length;
1215
that.enable( count > 0 );
1220
destroy: function ( dt, node, config ) {
1221
dt.off( config._eventNamespace );
1226
$.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) {
1227
var lc = item.toLowerCase();
1229
DataTable.ext.buttons[ 'select'+item+'s' ] = {
1230
text: i18n( 'select'+item+'s', 'Select '+lc+'s' ),
1231
className: 'buttons-select-'+lc+'s',
1232
action: function () {
1233
this.select.items( lc );
1235
init: function ( dt ) {
1238
dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) {
1239
that.active( items === lc );
1255
$(document).on( 'preInit.dt.dtSelect', function (e, ctx) {
1256
if ( e.namespace !== 'dt' ) {
1260
DataTable.select.init( new DataTable.Api( ctx ) );
1264
return DataTable.select;