datatables.net-select 3.1.3 → 4.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.
- package/js/dataTables.select.js +1454 -1755
- package/js/dataTables.select.min.js +3 -3
- package/js/dataTables.select.min.mjs +3 -3
- package/js/dataTables.select.mjs +1437 -1737
- package/package.json +3 -15
- package/types/types.d.ts +371 -370
package/js/dataTables.select.mjs
CHANGED
|
@@ -1,189 +1,159 @@
|
|
|
1
|
-
/*! Select for DataTables
|
|
2
|
-
*
|
|
1
|
+
/*! Select 4.0.0 for DataTables
|
|
2
|
+
* Copyright (c) SpryMedia Ltd - datatables.net/license
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import DataTable from 'datatables.net';
|
|
5
|
+
import DataTable, { util, Dom } from 'datatables.net';
|
|
7
6
|
|
|
8
|
-
// Allow reassignment of the $ variable
|
|
9
|
-
let $ = jQuery;
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
dt.select.selector(selector);
|
|
163
|
-
dt.select.items(items);
|
|
164
|
-
dt.select.style(style);
|
|
165
|
-
dt.select.blurable(blurable);
|
|
166
|
-
dt.select.toggleable(toggleable);
|
|
167
|
-
dt.select.info(info);
|
|
168
|
-
dt.select.keys(keys, keysWrap);
|
|
169
|
-
dt.select.selectable(selectable);
|
|
170
|
-
ctx._select.className = className;
|
|
171
|
-
|
|
172
|
-
// If the init options haven't enabled select, but there is a selectable
|
|
173
|
-
// class name, then enable
|
|
174
|
-
if (!setStyle && $(dt.table().node()).hasClass('selectable')) {
|
|
175
|
-
dt.select.style('os');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Insert a checkbox into the header if needed - might need to wait
|
|
179
|
-
// for init complete
|
|
180
|
-
if (headerCheckbox || headerCheckbox === 'select-page' || headerCheckbox === 'select-all') {
|
|
181
|
-
dt.ready(function () {
|
|
182
|
-
initCheckboxHeader(dt, headerCheckbox);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
8
|
+
if (!DataTable || !DataTable.versionCheck('3')) {
|
|
9
|
+
throw 'Error: Select requires DataTables 3 or newer';
|
|
10
|
+
}
|
|
11
|
+
DataTable.select = {
|
|
12
|
+
classes: {
|
|
13
|
+
checkbox: 'dt-select-checkbox'
|
|
14
|
+
},
|
|
15
|
+
init: function (dt) {
|
|
16
|
+
var ctx = dt.settings()[0];
|
|
17
|
+
if (ctx._select) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
var selectAndSave = function (e, settings, data) {
|
|
21
|
+
if (data === null || data.select === undefined) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Clear any currently selected rows, before restoring state
|
|
25
|
+
// None will be selected on first initialisation
|
|
26
|
+
if (dt.rows({ selected: true }).any()) {
|
|
27
|
+
dt.rows().deselect();
|
|
28
|
+
}
|
|
29
|
+
if (data.select.rows !== undefined) {
|
|
30
|
+
dt.rows(data.select.rows).select();
|
|
31
|
+
}
|
|
32
|
+
if (dt.columns({ selected: true }).any()) {
|
|
33
|
+
dt.columns().deselect();
|
|
34
|
+
}
|
|
35
|
+
if (data.select.columns !== undefined) {
|
|
36
|
+
dt.columns(data.select.columns).select();
|
|
37
|
+
}
|
|
38
|
+
if (dt.cells({ selected: true }).any()) {
|
|
39
|
+
dt.cells().deselect();
|
|
40
|
+
}
|
|
41
|
+
if (data.select.cells !== undefined) {
|
|
42
|
+
for (var i = 0; i < data.select.cells.length; i++) {
|
|
43
|
+
dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
dt.state.save();
|
|
47
|
+
};
|
|
48
|
+
dt.on('stateSaveParams', function (e, settings, data) {
|
|
49
|
+
data.select = {};
|
|
50
|
+
data.select.rows = dt.rows({ selected: true }).ids(true).toArray();
|
|
51
|
+
data.select.columns = dt.columns({ selected: true })[0];
|
|
52
|
+
data.select.cells = dt
|
|
53
|
+
.cells({ selected: true })[0]
|
|
54
|
+
.map(function (coords) {
|
|
55
|
+
return {
|
|
56
|
+
row: dt.row(coords.row).id(true),
|
|
57
|
+
column: coords.column
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
})
|
|
61
|
+
.on('stateLoadParams', selectAndSave)
|
|
62
|
+
.one('init', function () {
|
|
63
|
+
selectAndSave(undefined, undefined, dt.state.loaded());
|
|
64
|
+
});
|
|
65
|
+
var init = dt.init() ? dt.init().select : null;
|
|
66
|
+
var defaults = DataTable.defaults.select;
|
|
67
|
+
var opts = init === undefined ? defaults : init;
|
|
68
|
+
// Set defaults
|
|
69
|
+
var items = 'row';
|
|
70
|
+
var style = 'api';
|
|
71
|
+
var blurable = false;
|
|
72
|
+
var toggleable = true;
|
|
73
|
+
var selectable = null;
|
|
74
|
+
var info = true;
|
|
75
|
+
var selector = 'td, th';
|
|
76
|
+
var className = 'selected';
|
|
77
|
+
var headerCheckbox = true;
|
|
78
|
+
var setStyle = false;
|
|
79
|
+
var keys = false;
|
|
80
|
+
var keysWrap = false;
|
|
81
|
+
ctx._select = {
|
|
82
|
+
infoEls: []
|
|
83
|
+
};
|
|
84
|
+
// Initialisation customisations
|
|
85
|
+
if (opts === true) {
|
|
86
|
+
style = 'os';
|
|
87
|
+
setStyle = true;
|
|
88
|
+
}
|
|
89
|
+
else if (typeof opts === 'string') {
|
|
90
|
+
style = opts;
|
|
91
|
+
setStyle = true;
|
|
92
|
+
}
|
|
93
|
+
else if (util.is.plainObject(opts)) {
|
|
94
|
+
if (opts.blurable !== undefined) {
|
|
95
|
+
blurable = opts.blurable;
|
|
96
|
+
}
|
|
97
|
+
if (opts.toggleable !== undefined) {
|
|
98
|
+
toggleable = opts.toggleable;
|
|
99
|
+
}
|
|
100
|
+
if (opts.info !== undefined) {
|
|
101
|
+
info = opts.info;
|
|
102
|
+
}
|
|
103
|
+
if (opts.items !== undefined) {
|
|
104
|
+
items = opts.items;
|
|
105
|
+
}
|
|
106
|
+
if (opts.style !== undefined) {
|
|
107
|
+
style = opts.style;
|
|
108
|
+
setStyle = true;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
style = 'os';
|
|
112
|
+
setStyle = true;
|
|
113
|
+
}
|
|
114
|
+
if (opts.selector !== undefined) {
|
|
115
|
+
selector = opts.selector;
|
|
116
|
+
}
|
|
117
|
+
if (opts.className !== undefined) {
|
|
118
|
+
className = opts.className;
|
|
119
|
+
}
|
|
120
|
+
if (opts.headerCheckbox !== undefined) {
|
|
121
|
+
headerCheckbox = opts.headerCheckbox;
|
|
122
|
+
}
|
|
123
|
+
if (opts.selectable !== undefined) {
|
|
124
|
+
selectable = opts.selectable;
|
|
125
|
+
}
|
|
126
|
+
if (opts.keys !== undefined) {
|
|
127
|
+
keys = opts.keys;
|
|
128
|
+
}
|
|
129
|
+
if (opts.keysWrap !== undefined) {
|
|
130
|
+
keysWrap = opts.keysWrap;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
dt.select.selector(selector);
|
|
134
|
+
dt.select.items(items);
|
|
135
|
+
dt.select.style(style);
|
|
136
|
+
dt.select.blurable(blurable);
|
|
137
|
+
dt.select.toggleable(toggleable);
|
|
138
|
+
dt.select.info(info);
|
|
139
|
+
dt.select.keys(keys, keysWrap);
|
|
140
|
+
dt.select.selectable(selectable);
|
|
141
|
+
ctx._select.className = className;
|
|
142
|
+
// If the init options haven't enabled select, but there is a selectable
|
|
143
|
+
// class name, then enable
|
|
144
|
+
if (!setStyle && Dom.s(dt.table().node()).classHas('selectable')) {
|
|
145
|
+
dt.select.style('os');
|
|
146
|
+
}
|
|
147
|
+
// Insert a checkbox into the header if needed - might need to wait
|
|
148
|
+
// for init complete
|
|
149
|
+
if (headerCheckbox) {
|
|
150
|
+
dt.ready(function () {
|
|
151
|
+
initCheckboxHeader(dt, headerCheckbox);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
version: '4.0.0'
|
|
185
156
|
};
|
|
186
|
-
|
|
187
157
|
/*
|
|
188
158
|
|
|
189
159
|
Select is a collection of API methods, event handlers, event emitters and
|
|
@@ -194,12 +164,12 @@ features, with an overview of how they are implemented:
|
|
|
194
164
|
stored in:
|
|
195
165
|
|
|
196
166
|
* rows: a `_select_selected` property which contains a boolean value of the
|
|
197
|
-
DataTables' `
|
|
167
|
+
DataTables' `data` object for each row
|
|
198
168
|
* columns: a `_select_selected` property which contains a boolean value of the
|
|
199
|
-
DataTables' `
|
|
169
|
+
DataTables' `columns` object for each column
|
|
200
170
|
* cells: a `_selected_cells` property which contains an array of boolean values
|
|
201
|
-
of the `
|
|
202
|
-
|
|
171
|
+
of the `data` object for each row. The array is the same length as the columns
|
|
172
|
+
array, with each element of it representing a cell.
|
|
203
173
|
|
|
204
174
|
This method of using boolean flags allows Select to operate when nodes have not
|
|
205
175
|
been created for rows / cells (DataTables' defer rendering feature).
|
|
@@ -222,18 +192,18 @@ The `_select` object contains the following properties:
|
|
|
222
192
|
|
|
223
193
|
```
|
|
224
194
|
{
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
195
|
+
items:string - Can be `rows`, `columns` or `cells`. Defines what item
|
|
196
|
+
will be selected if the user is allowed to activate row
|
|
197
|
+
selection using the mouse.
|
|
198
|
+
style:string - Can be `none`, `single`, `multi` or `os`. Defines the
|
|
199
|
+
interaction style when selecting items
|
|
200
|
+
blurable:boolean - If row selection can be cleared by clicking outside of
|
|
201
|
+
the table
|
|
202
|
+
toggleable:boolean - If row selection can be cancelled by repeated clicking
|
|
203
|
+
on the row
|
|
204
|
+
info:boolean - If the selection summary should be shown in the table
|
|
205
|
+
information elements
|
|
206
|
+
infoEls:element[] - List of HTML elements with info elements for a table
|
|
237
207
|
}
|
|
238
208
|
```
|
|
239
209
|
|
|
@@ -248,11 +218,9 @@ Clicking on items can be used to select items. This is done by a simple event
|
|
|
248
218
|
handler that will select the items using the API methods.
|
|
249
219
|
|
|
250
220
|
*/
|
|
251
|
-
|
|
252
221
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
253
222
|
* Local functions
|
|
254
223
|
*/
|
|
255
|
-
|
|
256
224
|
/**
|
|
257
225
|
* Add one or more cells to the selection when shift clicking in OS selection
|
|
258
226
|
* style cell selection.
|
|
@@ -262,598 +230,525 @@ handler that will select the items using the API methods.
|
|
|
262
230
|
* click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
|
|
263
231
|
* should also be selected (and not 1-3, 1-4. etc)
|
|
264
232
|
*
|
|
265
|
-
* @param
|
|
266
|
-
* @param
|
|
267
|
-
* @param
|
|
268
|
-
* @private
|
|
233
|
+
* @param dt DataTable
|
|
234
|
+
* @param idx Cell index to select to
|
|
235
|
+
* @param last Cell index to select from
|
|
269
236
|
*/
|
|
270
237
|
function cellRange(dt, idx, last) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
indexes = dt.cells(rowIndexes, columnIndexes).flatten();
|
|
337
|
-
|
|
338
|
-
if (!dt.cells(idx, { selected: true }).any()) {
|
|
339
|
-
// Select range
|
|
340
|
-
dt.cells(indexes).select();
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
// Deselect range
|
|
344
|
-
dt.cells(indexes).deselect();
|
|
345
|
-
}
|
|
238
|
+
var indexes;
|
|
239
|
+
var columnIndexes;
|
|
240
|
+
var rowIndexes;
|
|
241
|
+
var selectColumns = function (start, end) {
|
|
242
|
+
if (start > end) {
|
|
243
|
+
var tmp = end;
|
|
244
|
+
end = start;
|
|
245
|
+
start = tmp;
|
|
246
|
+
}
|
|
247
|
+
var record = false;
|
|
248
|
+
return dt
|
|
249
|
+
.columns(':visible')
|
|
250
|
+
.indexes()
|
|
251
|
+
.filter(function (i) {
|
|
252
|
+
if (i === start) {
|
|
253
|
+
record = true;
|
|
254
|
+
}
|
|
255
|
+
if (i === end) {
|
|
256
|
+
// not else if, as start might === end
|
|
257
|
+
record = false;
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
return record;
|
|
261
|
+
});
|
|
262
|
+
};
|
|
263
|
+
var selectRows = function (start, end) {
|
|
264
|
+
var indexes = dt.rows({ search: 'applied' }).indexes();
|
|
265
|
+
// Which comes first - might need to swap
|
|
266
|
+
if (indexes.indexOf(start) > indexes.indexOf(end)) {
|
|
267
|
+
var tmp = end;
|
|
268
|
+
end = start;
|
|
269
|
+
start = tmp;
|
|
270
|
+
}
|
|
271
|
+
var record = false;
|
|
272
|
+
return indexes.filter(function (i) {
|
|
273
|
+
if (i === start) {
|
|
274
|
+
record = true;
|
|
275
|
+
}
|
|
276
|
+
if (i === end) {
|
|
277
|
+
record = false;
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
return record;
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
if (!dt.cells({ selected: true }).any() && !last) {
|
|
284
|
+
// select from the top left cell to this one
|
|
285
|
+
columnIndexes = selectColumns(0, idx.column);
|
|
286
|
+
rowIndexes = selectRows(0, idx.row);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Get column indexes between old and new
|
|
290
|
+
columnIndexes = selectColumns(last.column, idx.column);
|
|
291
|
+
rowIndexes = selectRows(last.row, idx.row);
|
|
292
|
+
}
|
|
293
|
+
indexes = dt.cells(rowIndexes, columnIndexes).flatten();
|
|
294
|
+
if (!dt.cells(idx, { selected: true }).any()) {
|
|
295
|
+
// Select range
|
|
296
|
+
dt.cells(indexes).select();
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
// Deselect range
|
|
300
|
+
dt.cells(indexes).deselect();
|
|
301
|
+
}
|
|
346
302
|
}
|
|
347
|
-
|
|
348
303
|
/**
|
|
349
|
-
* Get the
|
|
350
|
-
*
|
|
304
|
+
* Get a selector for the checkbox used
|
|
305
|
+
*
|
|
306
|
+
* @param asSelector Indicate if we want it as a selector, or as class names
|
|
307
|
+
* @returns Checkbox selector or class list
|
|
351
308
|
*/
|
|
352
|
-
function checkboxClass(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return selector
|
|
356
|
-
? name.replace(/ /g, '.')
|
|
357
|
-
: name;
|
|
309
|
+
function checkboxClass(asSelector) {
|
|
310
|
+
var name = DataTable.select.classes.checkbox;
|
|
311
|
+
return asSelector ? name.replace(/ /g, '.') : name;
|
|
358
312
|
}
|
|
359
|
-
|
|
360
313
|
/**
|
|
361
314
|
* Disable mouse selection by removing the selectors
|
|
362
315
|
*
|
|
363
|
-
* @param
|
|
364
|
-
* @private
|
|
316
|
+
* @param dt DataTable to remove events from
|
|
365
317
|
*/
|
|
366
318
|
function disableMouseSelection(dt) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
$('body').off('click.dtSelect' + _safeId(dt.table().node()));
|
|
319
|
+
var ctx = dt.settings()[0];
|
|
320
|
+
var selector = ctx._select.selector;
|
|
321
|
+
Dom.s(dt.table().container())
|
|
322
|
+
.off('mousedown.dtSelect', selector)
|
|
323
|
+
.off('mouseup.dtSelect', selector)
|
|
324
|
+
.off('click.dtSelect', selector);
|
|
325
|
+
Dom.s('body').off('click.dtSelect' + _safeId(dt.table().node()));
|
|
376
326
|
}
|
|
377
|
-
|
|
378
327
|
/**
|
|
379
328
|
* Attach mouse listeners to the table to allow mouse selection of items
|
|
380
329
|
*
|
|
381
|
-
* @param
|
|
382
|
-
* @private
|
|
330
|
+
* @param dt DataTable to remove events from
|
|
383
331
|
*/
|
|
384
332
|
function enableMouseSelection(dt) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
if ($(e.target).parents('html').length === 0) {
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// Don't blur in Editor form
|
|
487
|
-
if ($(e.target).parents('div.DTE').length) {
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
var event = $.Event('select-blur.dt');
|
|
492
|
-
eventTrigger(dt, event, [e.target, e]);
|
|
493
|
-
|
|
494
|
-
if (event.isDefaultPrevented()) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
clear(ctx, true);
|
|
499
|
-
}
|
|
500
|
-
});
|
|
333
|
+
var container = Dom.s(dt.table().container());
|
|
334
|
+
var ctx = dt.settings()[0];
|
|
335
|
+
var selector = ctx._select.selector;
|
|
336
|
+
var matchSelection;
|
|
337
|
+
container
|
|
338
|
+
.on('mousedown.dtSelect', selector, function (e) {
|
|
339
|
+
// Disallow text selection for shift clicking on the table so multi
|
|
340
|
+
// element selection doesn't look terrible!
|
|
341
|
+
if (e.shiftKey || e.metaKey || e.ctrlKey) {
|
|
342
|
+
container
|
|
343
|
+
.css('-moz-user-select', 'none')
|
|
344
|
+
.one('selectstart.dtSelect', selector, function () {
|
|
345
|
+
return false;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
if (window.getSelection) {
|
|
349
|
+
matchSelection = window.getSelection();
|
|
350
|
+
}
|
|
351
|
+
})
|
|
352
|
+
.on('mouseup.dtSelect', selector, function () {
|
|
353
|
+
// Allow text selection to occur again, Mozilla style (tested in FF
|
|
354
|
+
// 35.0.1 - still required)
|
|
355
|
+
container.css('-moz-user-select', '');
|
|
356
|
+
})
|
|
357
|
+
.on('click.dtSelect', selector, function (e) {
|
|
358
|
+
var items = dt.select.items();
|
|
359
|
+
var idx;
|
|
360
|
+
// If text was selected (click and drag), then we shouldn't change
|
|
361
|
+
// the row's selected state
|
|
362
|
+
if (matchSelection) {
|
|
363
|
+
var selection = window.getSelection();
|
|
364
|
+
// If the element that contains the selection is not in the
|
|
365
|
+
// table, we can ignore it This can happen if the developer
|
|
366
|
+
// selects text from the click event
|
|
367
|
+
if (!selection.anchorNode ||
|
|
368
|
+
Dom.s(selection.anchorNode.parentNode)
|
|
369
|
+
.closest('table')
|
|
370
|
+
.get(0) === dt.table().node()) {
|
|
371
|
+
if (selection !== matchSelection) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
var ctx = dt.settings()[0];
|
|
377
|
+
var container = dt.table().container();
|
|
378
|
+
// Ignore clicks inside a sub-table
|
|
379
|
+
if (Dom.s(e.target).closest('div.dt-container').get(0) != container) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
var cell = dt.cell(Dom.s(e.target).closest('td, th').get(0));
|
|
383
|
+
// Check the cell actually belongs to the host DataTable (so child
|
|
384
|
+
// rows, etc, are ignored)
|
|
385
|
+
if (!cell.any()) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
let res = eventTrigger(dt, 'user-select', [items, cell, e]);
|
|
389
|
+
if (res) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
var cellIndex = cell.index();
|
|
393
|
+
if (items === 'row') {
|
|
394
|
+
idx = cellIndex.row;
|
|
395
|
+
typeSelect(e, dt, ctx, 'row', idx);
|
|
396
|
+
}
|
|
397
|
+
else if (items === 'column') {
|
|
398
|
+
idx = cell.index().column;
|
|
399
|
+
typeSelect(e, dt, ctx, 'column', idx);
|
|
400
|
+
}
|
|
401
|
+
else if (items === 'cell') {
|
|
402
|
+
idx = cell.index();
|
|
403
|
+
typeSelect(e, dt, ctx, 'cell', idx);
|
|
404
|
+
}
|
|
405
|
+
ctx._select_lastCell = cellIndex;
|
|
406
|
+
});
|
|
407
|
+
// Blurable
|
|
408
|
+
Dom.s('body').on('click.dtSelect' + _safeId(dt.table().node()), function (e) {
|
|
409
|
+
if (ctx._select.blurable) {
|
|
410
|
+
// If the click was inside the DataTables container, don't blur
|
|
411
|
+
if (Dom.s(e.target).closest(dt.table().container()).count()) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// Ignore elements which have been removed from the DOM (i.e.
|
|
415
|
+
// paging buttons)
|
|
416
|
+
if (Dom.s(e.target).closest('html').count() === 0) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
// Don't blur in Editor form
|
|
420
|
+
if (Dom.s(e.target).closest('div.DTE').count()) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
let res = eventTrigger(dt, 'select-blur', [e.target, e]);
|
|
424
|
+
if (res) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
clear(ctx, true);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
501
430
|
}
|
|
502
|
-
|
|
503
431
|
/**
|
|
504
432
|
* Trigger an event on a DataTable
|
|
505
433
|
*
|
|
506
|
-
* @param
|
|
507
|
-
* @param
|
|
508
|
-
* @param
|
|
509
|
-
* @param
|
|
510
|
-
*
|
|
511
|
-
*
|
|
434
|
+
* @param api DataTable to trigger events on
|
|
435
|
+
* @param selected true if selected, false if deselected
|
|
436
|
+
* @param type Item type acting on
|
|
437
|
+
* @param any Require that there are values before triggering
|
|
438
|
+
* @returns `true` if the default action was prevented (i.e. execution should
|
|
439
|
+
* stop there)
|
|
512
440
|
*/
|
|
513
441
|
function eventTrigger(api, type, args, any) {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
$(api.table().node()).trigger(type, args);
|
|
442
|
+
if (any && !api.flatten().length) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (typeof type === 'string') {
|
|
446
|
+
type = type + '.dt';
|
|
447
|
+
}
|
|
448
|
+
args.unshift(api);
|
|
449
|
+
let ev = Dom.s(api.table().node()).trigger(type, true, args);
|
|
450
|
+
return ev.includes(false);
|
|
525
451
|
}
|
|
526
|
-
|
|
527
452
|
/**
|
|
528
453
|
* Determine if a column is a checkbox column
|
|
529
|
-
*
|
|
530
|
-
* @
|
|
454
|
+
*
|
|
455
|
+
* @param col DataTables column object
|
|
456
|
+
* @returns Boolean indicating if it is a checkbox column
|
|
531
457
|
*/
|
|
532
458
|
function isCheckboxColumn(col) {
|
|
533
|
-
|
|
459
|
+
return col.render && col.render._name === 'selectCheckbox';
|
|
534
460
|
}
|
|
535
|
-
|
|
536
461
|
/**
|
|
537
462
|
* Update the information element of the DataTable showing information about the
|
|
538
463
|
* items selected. This is done by adding tags to the existing text
|
|
539
464
|
*
|
|
540
|
-
* @param
|
|
541
|
-
* @private
|
|
465
|
+
* @param api DataTable to update
|
|
542
466
|
*/
|
|
543
467
|
function info(api, node) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
var existing = el.children('span.select-info');
|
|
591
|
-
|
|
592
|
-
if (existing.length) {
|
|
593
|
-
existing.remove();
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
if (output.text() !== '') {
|
|
597
|
-
el.append(output);
|
|
598
|
-
}
|
|
468
|
+
if (api.select.style() === 'api' || api.select.info() === false) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
var ctx = api.settings()[0];
|
|
472
|
+
var rowSet = ctx._select_set;
|
|
473
|
+
// Check that the ids are still in ctx.ids - row might have been deleted
|
|
474
|
+
// before it was unselected
|
|
475
|
+
if (!api.page.info().serverSide) {
|
|
476
|
+
for (var i = rowSet.length - 1; i >= 0; i--) {
|
|
477
|
+
if (!ctx.ids[rowSet[i]]) {
|
|
478
|
+
rowSet.splice(i, 1);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
var rows = rowSet.length
|
|
483
|
+
? rowSet.length
|
|
484
|
+
: api.rows({ selected: true }).count();
|
|
485
|
+
var columns = api.columns({ selected: true }).count();
|
|
486
|
+
var cells = api.cells({ selected: true }).count();
|
|
487
|
+
// If subtractive selection, then we need to take the number of rows and
|
|
488
|
+
// subtract those that have been deselected
|
|
489
|
+
if (ctx._select_mode === 'subtractive') {
|
|
490
|
+
rows = api.page.info().recordsDisplay - rowSet.length;
|
|
491
|
+
}
|
|
492
|
+
var add = function (el, name, num) {
|
|
493
|
+
el.append(Dom.c('span')
|
|
494
|
+
.classAdd('select-item')
|
|
495
|
+
.text(api.i18n('select.' + name + 's', {
|
|
496
|
+
_: '%d ' + name + 's selected',
|
|
497
|
+
0: '',
|
|
498
|
+
1: '1 ' + name + ' selected'
|
|
499
|
+
}, num)));
|
|
500
|
+
};
|
|
501
|
+
var el = Dom.s(node);
|
|
502
|
+
var output = Dom.c('span').classAdd('select-info');
|
|
503
|
+
add(output, 'row', rows);
|
|
504
|
+
add(output, 'column', columns);
|
|
505
|
+
add(output, 'cell', cells);
|
|
506
|
+
var existing = el.children('span.select-info');
|
|
507
|
+
if (existing.count()) {
|
|
508
|
+
existing.remove();
|
|
509
|
+
}
|
|
510
|
+
if (output.text() !== '') {
|
|
511
|
+
el.append(output);
|
|
512
|
+
}
|
|
599
513
|
}
|
|
600
|
-
|
|
601
514
|
/**
|
|
602
515
|
* Add a checkbox to the header for checkbox columns, allowing all rows to
|
|
603
516
|
* be selected, deselected or just to show the state.
|
|
604
517
|
*
|
|
605
|
-
* @param
|
|
606
|
-
* @param
|
|
518
|
+
* @param dt API
|
|
519
|
+
* @param headerCheckbox the header checkbox option
|
|
607
520
|
*/
|
|
608
|
-
function initCheckboxHeader(
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
});
|
|
521
|
+
function initCheckboxHeader(dt, headerCheckbox) {
|
|
522
|
+
var dtSettings = dt.settings()[0];
|
|
523
|
+
var dtInternalColumns = dtSettings.columns;
|
|
524
|
+
// Find any checkbox column(s)
|
|
525
|
+
dt.columns().iterator('column', function (s, idx) {
|
|
526
|
+
var col = dtInternalColumns[idx];
|
|
527
|
+
// Checkbox columns have a rendering function with a given name
|
|
528
|
+
if (!isCheckboxColumn(col)) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
var header = Dom.s(dt.column(idx).header());
|
|
532
|
+
var liner = header.find('div.dt-column-header');
|
|
533
|
+
if (liner.count()) {
|
|
534
|
+
header = liner;
|
|
535
|
+
}
|
|
536
|
+
if (!header.find('input').count()) {
|
|
537
|
+
// If no checkbox yet, insert one
|
|
538
|
+
var input = Dom.c('input')
|
|
539
|
+
.attr({
|
|
540
|
+
class: checkboxClass(false),
|
|
541
|
+
type: 'checkbox',
|
|
542
|
+
'aria-label': dt.i18n('select.aria.headerCheckbox', 'Select all rows')
|
|
543
|
+
})
|
|
544
|
+
.appendTo(header)
|
|
545
|
+
.on('change', function () {
|
|
546
|
+
if (input.prop('checked')) {
|
|
547
|
+
if (headerCheckbox == 'select-page') {
|
|
548
|
+
dt.rows({ page: 'current' }).select();
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
dt.rows({ search: 'applied' }).select();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
if (headerCheckbox == 'select-page') {
|
|
556
|
+
dt.rows({
|
|
557
|
+
page: 'current',
|
|
558
|
+
selected: true
|
|
559
|
+
}).deselect();
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
dt.rows({ selected: true }).deselect();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
})
|
|
566
|
+
.on('click', function (e) {
|
|
567
|
+
e.stopPropagation();
|
|
568
|
+
});
|
|
569
|
+
// Update the header checkbox's state when the selection in the
|
|
570
|
+
// table changes
|
|
571
|
+
dt.on('draw select deselect', function (e, pass, type) {
|
|
572
|
+
if (type === 'row' || !type) {
|
|
573
|
+
var nums = headerCheckboxState(dt, headerCheckbox);
|
|
574
|
+
if (nums.search &&
|
|
575
|
+
nums.search <= nums.count &&
|
|
576
|
+
nums.search === nums.available) {
|
|
577
|
+
input
|
|
578
|
+
.prop('checked', true)
|
|
579
|
+
.prop('indeterminate', false);
|
|
580
|
+
}
|
|
581
|
+
else if (nums.search === 0 && nums.count === 0) {
|
|
582
|
+
input
|
|
583
|
+
.prop('checked', false)
|
|
584
|
+
.prop('indeterminate', false);
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
input
|
|
588
|
+
.prop('checked', false)
|
|
589
|
+
.prop('indeterminate', true);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
});
|
|
685
595
|
}
|
|
686
|
-
|
|
687
596
|
function keysSet(dt) {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
}
|
|
785
|
-
else {
|
|
786
|
-
// Stop the rows from being able to gain focus
|
|
787
|
-
$(dt.rows().nodes()).removeAttr('tabindex');
|
|
788
|
-
|
|
789
|
-
// Nuke events
|
|
790
|
-
dt.off('draw.' + namespace);
|
|
791
|
-
$(document).off('keydown.' + namespace);
|
|
792
|
-
}
|
|
597
|
+
var ctx = dt.settings()[0];
|
|
598
|
+
var flag = ctx._select.keys;
|
|
599
|
+
var wrap = ctx._select.keysWrap;
|
|
600
|
+
var namespace = 'dts-keys-' + ctx.tableId;
|
|
601
|
+
if (flag) {
|
|
602
|
+
// Need a tabindex of the `tr` elements to make them focusable by the
|
|
603
|
+
// browser
|
|
604
|
+
Dom.s(dt.rows({ page: 'current' }).nodes().toArray()).attr('tabindex', 0);
|
|
605
|
+
dt.on('draw.' + namespace, function () {
|
|
606
|
+
Dom.s(dt.rows({ page: 'current' }).nodes().toArray()).attr('tabindex', 0);
|
|
607
|
+
});
|
|
608
|
+
// Listen on document for tab, up and down
|
|
609
|
+
Dom.s(document).on('keydown.' + namespace, function (e) {
|
|
610
|
+
var key = e.keyCode;
|
|
611
|
+
var active = document.activeElement;
|
|
612
|
+
// Can't use e.key as it wasn't widely supported until 2017
|
|
613
|
+
// 9 Tab
|
|
614
|
+
// 13 Return
|
|
615
|
+
// 32 Space
|
|
616
|
+
// 38 ArrowUp
|
|
617
|
+
// 40 ArrowDown
|
|
618
|
+
if (![9, 13, 32, 38, 40].includes(key)) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
var nodes = dt.rows({ page: 'current' }).nodes().toArray();
|
|
622
|
+
var idx = nodes.indexOf(active);
|
|
623
|
+
var preventDefault = true;
|
|
624
|
+
var pageInfo = dt.page.info();
|
|
625
|
+
// Only take an action if a row has focus
|
|
626
|
+
if (idx === -1) {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
if (key === 9) {
|
|
630
|
+
// Tab focus change
|
|
631
|
+
if (e.shift === false && idx === nodes.length - 1) {
|
|
632
|
+
keysPageChange(dt, 'next', ':first-child');
|
|
633
|
+
}
|
|
634
|
+
else if (e.shift === true && idx === 0) {
|
|
635
|
+
keysPageChange(dt, 'previous', ':last-child');
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
// Browser will do it for us
|
|
639
|
+
preventDefault = false;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
else if (key === 13 || key === 32) {
|
|
643
|
+
// Row selection / deselection
|
|
644
|
+
var row = dt.row(active);
|
|
645
|
+
if (row.selected()) {
|
|
646
|
+
row.deselect();
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
row.select();
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
else if (key === 38) {
|
|
653
|
+
// Move up
|
|
654
|
+
if (idx > 0) {
|
|
655
|
+
nodes[idx - 1].focus();
|
|
656
|
+
}
|
|
657
|
+
else if (pageInfo.start > 0) {
|
|
658
|
+
// Shift back to the previous page
|
|
659
|
+
keysPageChange(dt, 'previous', ':last-child');
|
|
660
|
+
}
|
|
661
|
+
else if (wrap) {
|
|
662
|
+
// Wrap
|
|
663
|
+
keysPageChange(dt, 'last', ':last-child');
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
// Move down
|
|
668
|
+
if (idx < nodes.length - 1) {
|
|
669
|
+
nodes[idx + 1].focus();
|
|
670
|
+
}
|
|
671
|
+
else if (pageInfo.page < pageInfo.pages - 1) {
|
|
672
|
+
// Move on to the next page
|
|
673
|
+
keysPageChange(dt, 'next', ':first-child');
|
|
674
|
+
}
|
|
675
|
+
else if (wrap) {
|
|
676
|
+
// Wrap
|
|
677
|
+
keysPageChange(dt, 'first', ':first-child');
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
if (preventDefault) {
|
|
681
|
+
e.stopPropagation();
|
|
682
|
+
e.preventDefault();
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
// Stop the rows from being able to gain focus
|
|
688
|
+
Dom.s(dt.rows().nodes().toArray()).attrRemove('tabindex');
|
|
689
|
+
// Nuke events
|
|
690
|
+
dt.off('draw.' + namespace);
|
|
691
|
+
Dom.s(document).off('keydown.' + namespace);
|
|
692
|
+
}
|
|
793
693
|
}
|
|
794
|
-
|
|
795
694
|
/**
|
|
796
695
|
* Change change to a new page and focus
|
|
797
696
|
*
|
|
798
|
-
* @param
|
|
697
|
+
* @param dt DataTable instance
|
|
698
|
+
* @param page Which page to change to
|
|
699
|
+
* @param focus Which row to focus on
|
|
799
700
|
*/
|
|
800
701
|
function keysPageChange(dt, page, focus) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
.draw(false);
|
|
702
|
+
dt.one('draw', function () {
|
|
703
|
+
dt.row(focus).node().focus();
|
|
704
|
+
})
|
|
705
|
+
.page(page)
|
|
706
|
+
.draw(false);
|
|
807
707
|
}
|
|
808
|
-
|
|
809
708
|
/**
|
|
810
709
|
* Determine the counts used to define the header checkbox's state
|
|
811
710
|
*
|
|
812
|
-
* @param
|
|
813
|
-
* @param
|
|
711
|
+
* @param dt DT API
|
|
712
|
+
* @param headerCheckbox Configuration for what the header checkbox does
|
|
814
713
|
* @returns Counts object
|
|
815
714
|
*/
|
|
816
715
|
function headerCheckboxState(dt, headerCheckbox) {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
count: count,
|
|
853
|
-
search: search
|
|
854
|
-
}
|
|
716
|
+
var ctx = dt.settings()[0];
|
|
717
|
+
var selectable = ctx._select.selectable;
|
|
718
|
+
var available = 0;
|
|
719
|
+
var count = headerCheckbox == 'select-page'
|
|
720
|
+
? dt.rows({ page: 'current', selected: true }).count()
|
|
721
|
+
: dt.rows({ selected: true }).count();
|
|
722
|
+
var search = headerCheckbox == 'select-page'
|
|
723
|
+
? dt.rows({ page: 'current', selected: true }).count()
|
|
724
|
+
: dt.rows({ search: 'applied', selected: true }).count();
|
|
725
|
+
if (!selectable) {
|
|
726
|
+
available =
|
|
727
|
+
headerCheckbox == 'select-page'
|
|
728
|
+
? dt.rows({ page: 'current' }).count()
|
|
729
|
+
: dt.rows({ search: 'applied' }).count();
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
// Need to count how many rows are actually selectable to know if all
|
|
733
|
+
// selectable rows are selected or not
|
|
734
|
+
var indexes = headerCheckbox == 'select-page'
|
|
735
|
+
? dt.rows({ page: 'current' }).indexes().toArray()
|
|
736
|
+
: dt.rows({ search: 'applied' }).indexes().toArray();
|
|
737
|
+
for (var i = 0; i < indexes.length; i++) {
|
|
738
|
+
// For speed I use the internal DataTables object.
|
|
739
|
+
var rowInternal = ctx.data[indexes[i]];
|
|
740
|
+
var result = selectable(rowInternal.data, rowInternal.tr, indexes[i]);
|
|
741
|
+
if (result) {
|
|
742
|
+
available++;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return {
|
|
747
|
+
available: available,
|
|
748
|
+
count: count,
|
|
749
|
+
search: search
|
|
750
|
+
};
|
|
855
751
|
}
|
|
856
|
-
|
|
857
752
|
/**
|
|
858
753
|
* Initialisation of a new table. Attach event handlers and callbacks to allow
|
|
859
754
|
* Select to operate correctly.
|
|
@@ -861,1131 +756,936 @@ function headerCheckboxState(dt, headerCheckbox) {
|
|
|
861
756
|
* This will occur _after_ the initial DataTables initialisation, although
|
|
862
757
|
* before Ajax data is rendered, if there is ajax data
|
|
863
758
|
*
|
|
864
|
-
* @param
|
|
865
|
-
* @private
|
|
759
|
+
* @param ctx Settings object to operate on
|
|
866
760
|
*/
|
|
867
761
|
function init(ctx) {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
// Clean up and release
|
|
936
|
-
api.on('destroy.dtSelect', function () {
|
|
937
|
-
// Remove class directly rather than calling deselect - which would trigger events
|
|
938
|
-
$(api.rows({ selected: true }).nodes()).removeClass(api.settings()[0]._select.className);
|
|
939
|
-
|
|
940
|
-
$('input.' + checkboxClass(true), api.table().header()).remove();
|
|
941
|
-
|
|
942
|
-
disableMouseSelection(api);
|
|
943
|
-
api.off('.dtSelect');
|
|
944
|
-
$('body').off('.dtSelect' + _safeId(api.table().node()));
|
|
945
|
-
});
|
|
762
|
+
var api = new DataTable.Api(ctx);
|
|
763
|
+
ctx._select_init = true;
|
|
764
|
+
// When `additive` then `_select_set` contains a list of the row ids that
|
|
765
|
+
// are selected. If `subtractive` then all rows are selected, except those
|
|
766
|
+
// in `_select_set`, which is a list of ids.
|
|
767
|
+
ctx._select_mode = 'additive';
|
|
768
|
+
ctx._select_set = [];
|
|
769
|
+
// Row callback so that classes can be added to rows and cells if the item
|
|
770
|
+
// was selected before the element was created. This will happen with the
|
|
771
|
+
// `deferRender` option enabled.
|
|
772
|
+
//
|
|
773
|
+
// This method of attaching to `aoRowCreatedCallback` is a hack until
|
|
774
|
+
// DataTables has proper events for row manipulation If you are reviewing
|
|
775
|
+
// this code to create your own plug-ins, please do not do this!
|
|
776
|
+
ctx.callbacks.rowCreated.push(function (row, data, index) {
|
|
777
|
+
var i, ien;
|
|
778
|
+
var d = ctx.data[index];
|
|
779
|
+
var id = api.row(index).id();
|
|
780
|
+
// Row
|
|
781
|
+
if (d._select_selected ||
|
|
782
|
+
(ctx._select_mode === 'additive' && ctx._select_set.includes(id)) ||
|
|
783
|
+
(ctx._select_mode === 'subtractive' &&
|
|
784
|
+
!ctx._select_set.includes(id))) {
|
|
785
|
+
d._select_selected = true;
|
|
786
|
+
Dom.s(row)
|
|
787
|
+
.classAdd(ctx._select.className)
|
|
788
|
+
.find('input.' + checkboxClass(true))
|
|
789
|
+
.prop('checked', true);
|
|
790
|
+
}
|
|
791
|
+
// Cells and columns - if separated out, we would need to do two
|
|
792
|
+
// loops, so it makes sense to combine them into a single one
|
|
793
|
+
for (i = 0, ien = ctx.columns.length; i < ien; i++) {
|
|
794
|
+
if (ctx.columns[i]._select_selected ||
|
|
795
|
+
(d._selected_cells && d._selected_cells[i])) {
|
|
796
|
+
Dom.s(d.cells[i]).classAdd(ctx._select.className);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
_cumulativeEvents(api);
|
|
801
|
+
// Update the table information element with selected item summary
|
|
802
|
+
api.on('info.dt', function (e, ctx, node) {
|
|
803
|
+
// Store the info node for updating on select / deselect
|
|
804
|
+
if (!ctx._select.infoEls.includes(node)) {
|
|
805
|
+
ctx._select.infoEls.push(node);
|
|
806
|
+
}
|
|
807
|
+
info(api, node);
|
|
808
|
+
});
|
|
809
|
+
api.on('select.dtSelect.dt deselect.dtSelect.dt', function () {
|
|
810
|
+
ctx._select.infoEls.forEach(function (el) {
|
|
811
|
+
info(api, el);
|
|
812
|
+
});
|
|
813
|
+
api.state.save();
|
|
814
|
+
});
|
|
815
|
+
// Clean up and release
|
|
816
|
+
api.on('destroy.dtSelect', function () {
|
|
817
|
+
// Remove class directly rather than calling deselect - which would
|
|
818
|
+
// trigger events
|
|
819
|
+
Dom.s(api.rows({ selected: true }).nodes().toArray()).classRemove(api.settings()[0]._select.className);
|
|
820
|
+
Dom.s(api.table().header())
|
|
821
|
+
.find('input.' + checkboxClass(true))
|
|
822
|
+
.remove();
|
|
823
|
+
disableMouseSelection(api);
|
|
824
|
+
api.off('.dtSelect');
|
|
825
|
+
Dom.s('body').off('.dtSelect' + _safeId(api.table().node()));
|
|
826
|
+
});
|
|
946
827
|
}
|
|
947
|
-
|
|
948
828
|
/**
|
|
949
829
|
* Add one or more items (rows or columns) to the selection when shift clicking
|
|
950
830
|
* in OS selection style
|
|
951
831
|
*
|
|
952
|
-
* @param
|
|
953
|
-
* @param
|
|
954
|
-
* @param
|
|
955
|
-
* @param
|
|
956
|
-
* @private
|
|
832
|
+
* @param dt DataTable
|
|
833
|
+
* @param type Row or column range selector
|
|
834
|
+
* @param idx Item index to select to
|
|
835
|
+
* @param last Item index to select from
|
|
957
836
|
*/
|
|
958
837
|
function rowColumnRange(dt, type, idx, last) {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
indexes.splice(indexes.indexOf(idx), 1);
|
|
988
|
-
dt[type + 's'](indexes).deselect();
|
|
989
|
-
}
|
|
838
|
+
// Add a range of rows from the last selected row to this one
|
|
839
|
+
var indexes = dt[type + 's']({ search: 'applied' }).indexes();
|
|
840
|
+
var idx1 = indexes.indexOf(last);
|
|
841
|
+
var idx2 = indexes.indexOf(idx);
|
|
842
|
+
if (!dt[type + 's']({ selected: true }).any() && idx1 === -1) {
|
|
843
|
+
// select from top to here - slightly odd, but both Windows and Mac OS
|
|
844
|
+
// do this
|
|
845
|
+
indexes.splice(indexes.indexOf(idx) + 1, indexes.length);
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
// reverse so we can shift click 'up' as well as down
|
|
849
|
+
if (idx1 > idx2) {
|
|
850
|
+
var tmp = idx2;
|
|
851
|
+
idx2 = idx1;
|
|
852
|
+
idx1 = tmp;
|
|
853
|
+
}
|
|
854
|
+
indexes.splice(idx2 + 1, indexes.length);
|
|
855
|
+
indexes.splice(0, idx1);
|
|
856
|
+
}
|
|
857
|
+
if (!dt[type](idx, { selected: true }).any()) {
|
|
858
|
+
// Select range
|
|
859
|
+
dt[type + 's'](indexes).select();
|
|
860
|
+
}
|
|
861
|
+
else {
|
|
862
|
+
// Deselect range - need to keep the clicked on row selected
|
|
863
|
+
indexes.splice(indexes.indexOf(idx), 1);
|
|
864
|
+
dt[type + 's'](indexes).deselect();
|
|
865
|
+
}
|
|
990
866
|
}
|
|
991
|
-
|
|
992
867
|
/**
|
|
993
868
|
* Clear all selected items
|
|
994
869
|
*
|
|
995
|
-
* @param
|
|
996
|
-
* @param
|
|
997
|
-
* of selection style
|
|
998
|
-
* @private
|
|
870
|
+
* @param ctx Settings object of the host DataTable
|
|
871
|
+
* @param force Force the de-selection to happen, regardless of selection style
|
|
999
872
|
*/
|
|
1000
|
-
function clear(ctx, force) {
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
873
|
+
function clear(ctx, force = false) {
|
|
874
|
+
if (force || ctx._select.style === 'single') {
|
|
875
|
+
var api = new DataTable.Api(ctx);
|
|
876
|
+
api.rows({ selected: true }).deselect();
|
|
877
|
+
api.columns({ selected: true }).deselect();
|
|
878
|
+
api.cells({ selected: true }).deselect();
|
|
879
|
+
}
|
|
1008
880
|
}
|
|
1009
|
-
|
|
1010
881
|
/**
|
|
1011
882
|
* Select items based on the current configuration for style and items.
|
|
1012
883
|
*
|
|
1013
|
-
* @param
|
|
1014
|
-
* @param
|
|
1015
|
-
* @param
|
|
1016
|
-
* @param
|
|
1017
|
-
* @param
|
|
1018
|
-
* @private
|
|
884
|
+
* @param e Mouse event object
|
|
885
|
+
* @param dt DataTable
|
|
886
|
+
* @param ctx Settings object of the host DataTable
|
|
887
|
+
* @param type Items to select
|
|
888
|
+
* @param idx Index of the item to select
|
|
1019
889
|
*/
|
|
1020
890
|
function typeSelect(e, dt, ctx, type, idx) {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
type,
|
|
1070
|
-
idx,
|
|
1071
|
-
ctx._select_lastCell ? ctx._select_lastCell[type] : null
|
|
1072
|
-
);
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
else {
|
|
1076
|
-
dt[type](idx).select(!isSelected);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
else {
|
|
1080
|
-
dt[type](idx).select(!isSelected);
|
|
1081
|
-
}
|
|
891
|
+
var style = dt.select.style();
|
|
892
|
+
var toggleable = dt.select.toggleable();
|
|
893
|
+
var isSelected = dt[type](idx, { selected: true }).any();
|
|
894
|
+
if (isSelected && !toggleable) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (style === 'os') {
|
|
898
|
+
if (e.ctrlKey || e.metaKey) {
|
|
899
|
+
// Add or remove from the selection
|
|
900
|
+
dt[type](idx).select(!isSelected);
|
|
901
|
+
}
|
|
902
|
+
else if (e.shiftKey) {
|
|
903
|
+
if (type === 'cell') {
|
|
904
|
+
cellRange(dt, idx, ctx._select_lastCell || null);
|
|
905
|
+
}
|
|
906
|
+
else {
|
|
907
|
+
rowColumnRange(dt, type, idx, ctx._select_lastCell ? ctx._select_lastCell[type] : null);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
// No cmd or shift click - deselect if selected, or select
|
|
912
|
+
// this row only
|
|
913
|
+
var selected = dt[type + 's']({ selected: true });
|
|
914
|
+
if (isSelected && selected.flatten().length === 1) {
|
|
915
|
+
dt[type](idx).deselect();
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
selected.deselect();
|
|
919
|
+
dt[type](idx).select();
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
else if (style == 'multi+shift') {
|
|
924
|
+
if (e.shiftKey) {
|
|
925
|
+
if (type === 'cell') {
|
|
926
|
+
cellRange(dt, idx, ctx._select_lastCell || null);
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
rowColumnRange(dt, type, idx, ctx._select_lastCell ? ctx._select_lastCell[type] : null);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
dt[type](idx).select(!isSelected);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
else {
|
|
937
|
+
dt[type](idx).select(!isSelected);
|
|
938
|
+
}
|
|
1082
939
|
}
|
|
1083
|
-
|
|
940
|
+
/**
|
|
941
|
+
* Get an id from an element
|
|
942
|
+
*
|
|
943
|
+
* @param node
|
|
944
|
+
* @returns The id
|
|
945
|
+
*/
|
|
1084
946
|
function _safeId(node) {
|
|
1085
|
-
|
|
947
|
+
return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
|
|
1086
948
|
}
|
|
1087
|
-
|
|
1088
949
|
/**
|
|
1089
950
|
* Set up event handlers for cumulative selection
|
|
1090
951
|
*
|
|
1091
|
-
* @param
|
|
952
|
+
* @param api DT API instance
|
|
1092
953
|
*/
|
|
1093
954
|
function _cumulativeEvents(api) {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
else {
|
|
1128
|
-
// List is of rows which are deselected, so add it!
|
|
1129
|
-
_add(api, ctx._select_set, indexes);
|
|
1130
|
-
}
|
|
1131
|
-
});
|
|
955
|
+
// Add event listeners to add / remove from the _select_set
|
|
956
|
+
api.on('select', function (e, dt, type, indexes) {
|
|
957
|
+
// Only support for rows at the moment
|
|
958
|
+
if (type !== 'row') {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
var ctx = api.settings()[0];
|
|
962
|
+
if (ctx._select_mode === 'additive') {
|
|
963
|
+
// Add row to the selection list if it isn't already there
|
|
964
|
+
_add(api, ctx._select_set, indexes);
|
|
965
|
+
}
|
|
966
|
+
else {
|
|
967
|
+
// Subtractive - if a row is selected it should not in the list
|
|
968
|
+
// as in subtractive mode the list gives the rows which are not
|
|
969
|
+
// selected
|
|
970
|
+
_remove(api, ctx._select_set, indexes);
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
api.on('deselect', function (e, dt, type, indexes) {
|
|
974
|
+
// Only support for rows at the moment
|
|
975
|
+
if (type !== 'row') {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
var ctx = api.settings()[0];
|
|
979
|
+
if (ctx._select_mode === 'additive') {
|
|
980
|
+
// List is of those rows selected, so remove it
|
|
981
|
+
_remove(api, ctx._select_set, indexes);
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
// List is of rows which are deselected, so add it!
|
|
985
|
+
_add(api, ctx._select_set, indexes);
|
|
986
|
+
}
|
|
987
|
+
});
|
|
1132
988
|
}
|
|
1133
|
-
|
|
1134
989
|
function _add(api, arr, indexes) {
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
}
|
|
990
|
+
for (var i = 0; i < indexes.length; i++) {
|
|
991
|
+
var id = api.row(indexes[i]).id();
|
|
992
|
+
if (id && id !== 'undefined' && !arr.includes(id)) {
|
|
993
|
+
arr.push(id);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
1142
996
|
}
|
|
1143
|
-
|
|
1144
997
|
function _remove(api, arr, indexes) {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
}
|
|
998
|
+
for (var i = 0; i < indexes.length; i++) {
|
|
999
|
+
var id = api.row(indexes[i]).id();
|
|
1000
|
+
var idx = arr.indexOf(id);
|
|
1001
|
+
if (idx !== -1) {
|
|
1002
|
+
arr.splice(idx, 1);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1153
1005
|
}
|
|
1154
|
-
|
|
1155
1006
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
1156
1007
|
* DataTables selectors
|
|
1157
1008
|
*/
|
|
1158
|
-
|
|
1159
1009
|
// row and column are basically identical just assigned to different properties
|
|
1160
1010
|
// and checking a different array, so we can dynamically create the functions to
|
|
1161
1011
|
// reduce the code size
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
)
|
|
1185
|
-
) {
|
|
1186
|
-
out.push(indexes[i]);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
return out;
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
);
|
|
1194
|
-
|
|
1012
|
+
[
|
|
1013
|
+
{ type: 'row', prop: 'data' },
|
|
1014
|
+
{ type: 'column', prop: 'columns' }
|
|
1015
|
+
].forEach(function (o) {
|
|
1016
|
+
DataTable.ext.selector[o.type].push(function (settings, opts, indexes) {
|
|
1017
|
+
var selected = opts.selected;
|
|
1018
|
+
var data;
|
|
1019
|
+
var out = [];
|
|
1020
|
+
if (selected !== true && selected !== false) {
|
|
1021
|
+
return indexes;
|
|
1022
|
+
}
|
|
1023
|
+
for (var i = 0, ien = indexes.length; i < ien; i++) {
|
|
1024
|
+
data = settings[o.prop][indexes[i]];
|
|
1025
|
+
if (data &&
|
|
1026
|
+
((selected === true && data._select_selected === true) ||
|
|
1027
|
+
(selected === false && !data._select_selected))) {
|
|
1028
|
+
out.push(indexes[i]);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return out;
|
|
1032
|
+
});
|
|
1033
|
+
});
|
|
1195
1034
|
DataTable.ext.selector.cell.push(function (settings, opts, cells) {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
) {
|
|
1216
|
-
out.push(cells[i]);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
return out;
|
|
1035
|
+
var selected = opts.selected;
|
|
1036
|
+
var rowData;
|
|
1037
|
+
var out = [];
|
|
1038
|
+
if (selected === undefined) {
|
|
1039
|
+
return cells;
|
|
1040
|
+
}
|
|
1041
|
+
for (var i = 0, ien = cells.length; i < ien; i++) {
|
|
1042
|
+
rowData = settings.data[cells[i].row];
|
|
1043
|
+
if (rowData &&
|
|
1044
|
+
((selected === true &&
|
|
1045
|
+
rowData._selected_cells &&
|
|
1046
|
+
rowData._selected_cells[cells[i].column] === true) ||
|
|
1047
|
+
(selected === false &&
|
|
1048
|
+
(!rowData._selected_cells ||
|
|
1049
|
+
!rowData._selected_cells[cells[i].column])))) {
|
|
1050
|
+
out.push(cells[i]);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
return out;
|
|
1221
1054
|
});
|
|
1222
|
-
|
|
1223
1055
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
1224
1056
|
* DataTables API
|
|
1225
1057
|
*
|
|
1226
1058
|
* For complete documentation, please refer to the docs/api directory or the
|
|
1227
1059
|
* DataTables site
|
|
1228
1060
|
*/
|
|
1229
|
-
|
|
1230
1061
|
// Local variables to improve compression
|
|
1231
1062
|
var apiRegister = DataTable.Api.register;
|
|
1232
1063
|
var apiRegisterPlural = DataTable.Api.registerPlural;
|
|
1233
|
-
|
|
1234
1064
|
apiRegister('select()', function () {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1065
|
+
return this.iterator('table', function (ctx) {
|
|
1066
|
+
DataTable.select.init(new DataTable.Api(ctx));
|
|
1067
|
+
});
|
|
1238
1068
|
});
|
|
1239
|
-
|
|
1240
1069
|
apiRegister('select.blurable()', function (flag) {
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
});
|
|
1070
|
+
if (flag === undefined) {
|
|
1071
|
+
return this.context[0]._select.blurable;
|
|
1072
|
+
}
|
|
1073
|
+
return this.iterator('table', function (ctx) {
|
|
1074
|
+
ctx._select.blurable = flag;
|
|
1075
|
+
});
|
|
1248
1076
|
});
|
|
1249
|
-
|
|
1250
1077
|
apiRegister('select.toggleable()', function (flag) {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
});
|
|
1078
|
+
if (flag === undefined) {
|
|
1079
|
+
return this.context[0]._select.toggleable;
|
|
1080
|
+
}
|
|
1081
|
+
return this.iterator('table', function (ctx) {
|
|
1082
|
+
ctx._select.toggleable = flag;
|
|
1083
|
+
});
|
|
1258
1084
|
});
|
|
1259
|
-
|
|
1260
1085
|
apiRegister('select.info()', function (flag) {
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
});
|
|
1086
|
+
if (flag === undefined) {
|
|
1087
|
+
return this.context[0]._select.info;
|
|
1088
|
+
}
|
|
1089
|
+
return this.iterator('table', function (ctx) {
|
|
1090
|
+
ctx._select.info = flag;
|
|
1091
|
+
});
|
|
1268
1092
|
});
|
|
1269
|
-
|
|
1270
1093
|
apiRegister('select.items()', function (items) {
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
|
|
1279
|
-
});
|
|
1094
|
+
if (items === undefined) {
|
|
1095
|
+
return this.context[0]._select.items;
|
|
1096
|
+
}
|
|
1097
|
+
return this.iterator('table', function (ctx) {
|
|
1098
|
+
ctx._select.items = items;
|
|
1099
|
+
eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
|
|
1100
|
+
});
|
|
1280
1101
|
});
|
|
1281
|
-
|
|
1282
1102
|
apiRegister('select.keys()', function (flag, wrap) {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
keysSet(new DataTable.Api(ctx));
|
|
1296
|
-
});
|
|
1103
|
+
if (flag === undefined) {
|
|
1104
|
+
return this.context[0]._select.keys;
|
|
1105
|
+
}
|
|
1106
|
+
return this.iterator('table', function (ctx) {
|
|
1107
|
+
if (!ctx._select) {
|
|
1108
|
+
DataTable.select.init(new DataTable.Api(ctx));
|
|
1109
|
+
}
|
|
1110
|
+
ctx._select.keys = flag;
|
|
1111
|
+
ctx._select.keysWrap = wrap;
|
|
1112
|
+
keysSet(new DataTable.Api(ctx));
|
|
1113
|
+
});
|
|
1297
1114
|
});
|
|
1298
|
-
|
|
1299
1115
|
// Takes effect from the _next_ selection. None disables future selection, but
|
|
1300
1116
|
// does not clear the current selection. Use the `deselect` methods for that
|
|
1301
1117
|
apiRegister('select.style()', function (style) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
else {
|
|
1328
|
-
disableMouseSelection(dt);
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
|
|
1332
|
-
});
|
|
1118
|
+
if (style === undefined) {
|
|
1119
|
+
return this.context[0]._select.style;
|
|
1120
|
+
}
|
|
1121
|
+
return this.iterator('table', function (ctx) {
|
|
1122
|
+
if (!ctx._select) {
|
|
1123
|
+
DataTable.select.init(new DataTable.Api(ctx));
|
|
1124
|
+
}
|
|
1125
|
+
if (!ctx._select_init) {
|
|
1126
|
+
init(ctx);
|
|
1127
|
+
}
|
|
1128
|
+
ctx._select.style = style;
|
|
1129
|
+
// Add / remove mouse event handlers. They aren't required when only
|
|
1130
|
+
// API selection is available
|
|
1131
|
+
var dt = new DataTable.Api(ctx);
|
|
1132
|
+
if (style !== 'api') {
|
|
1133
|
+
dt.ready(function () {
|
|
1134
|
+
disableMouseSelection(dt);
|
|
1135
|
+
enableMouseSelection(dt);
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
else {
|
|
1139
|
+
disableMouseSelection(dt);
|
|
1140
|
+
}
|
|
1141
|
+
eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
|
|
1142
|
+
});
|
|
1333
1143
|
});
|
|
1334
|
-
|
|
1335
1144
|
apiRegister('select.selector()', function (selector) {
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
else {
|
|
1355
|
-
disableMouseSelection(dt);
|
|
1356
|
-
}
|
|
1357
|
-
});
|
|
1145
|
+
if (selector === undefined) {
|
|
1146
|
+
return this.context[0]._select.selector;
|
|
1147
|
+
}
|
|
1148
|
+
return this.iterator('table', function (ctx) {
|
|
1149
|
+
var dt = new DataTable.Api(ctx);
|
|
1150
|
+
var style = ctx._select.style;
|
|
1151
|
+
disableMouseSelection(dt);
|
|
1152
|
+
ctx._select.selector = selector;
|
|
1153
|
+
if (style && style !== 'api') {
|
|
1154
|
+
dt.ready(function () {
|
|
1155
|
+
disableMouseSelection(dt);
|
|
1156
|
+
enableMouseSelection(dt);
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
else {
|
|
1160
|
+
disableMouseSelection(dt);
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1358
1163
|
});
|
|
1359
|
-
|
|
1360
1164
|
apiRegister('select.selectable()', function (set) {
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
return ctx._select.selectable;
|
|
1165
|
+
let ctx = this.context[0];
|
|
1166
|
+
if (set) {
|
|
1167
|
+
ctx._select.selectable = set;
|
|
1168
|
+
return this;
|
|
1169
|
+
}
|
|
1170
|
+
return ctx._select.selectable;
|
|
1369
1171
|
});
|
|
1370
|
-
|
|
1371
1172
|
apiRegister('select.last()', function (set) {
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
return ctx._select_lastCell;
|
|
1173
|
+
let ctx = this.context[0];
|
|
1174
|
+
if (set) {
|
|
1175
|
+
ctx._select_lastCell = set;
|
|
1176
|
+
return this;
|
|
1177
|
+
}
|
|
1178
|
+
return ctx._select_lastCell;
|
|
1380
1179
|
});
|
|
1381
|
-
|
|
1382
1180
|
apiRegister('select.cumulative()', function (mode) {
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
mode: ctx._select_mode,
|
|
1416
|
-
rows: ctx._select_set
|
|
1417
|
-
};
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
return null;
|
|
1181
|
+
if (mode) {
|
|
1182
|
+
return this.iterator('table', function (ctx) {
|
|
1183
|
+
if (ctx._select_mode === mode) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
var dt = new DataTable.Api(ctx);
|
|
1187
|
+
// Convert from the current mode, to the new
|
|
1188
|
+
if (mode === 'subtractive') {
|
|
1189
|
+
// For subtractive mode we track the row ids which are not
|
|
1190
|
+
// selected
|
|
1191
|
+
var unselected = dt.rows({ selected: false }).ids().toArray();
|
|
1192
|
+
ctx._select_mode = mode;
|
|
1193
|
+
ctx._select_set.length = 0;
|
|
1194
|
+
ctx._select_set.push.apply(ctx._select_set, unselected);
|
|
1195
|
+
}
|
|
1196
|
+
else {
|
|
1197
|
+
// Switching to additive, so selected rows are to be used
|
|
1198
|
+
var selected = dt.rows({ selected: true }).ids().toArray();
|
|
1199
|
+
ctx._select_mode = mode;
|
|
1200
|
+
ctx._select_set.length = 0;
|
|
1201
|
+
ctx._select_set.push.apply(ctx._select_set, selected);
|
|
1202
|
+
}
|
|
1203
|
+
}).draw(false);
|
|
1204
|
+
}
|
|
1205
|
+
let ctx = this.context[0];
|
|
1206
|
+
if (ctx && ctx._select_set) {
|
|
1207
|
+
return {
|
|
1208
|
+
mode: ctx._select_mode,
|
|
1209
|
+
rows: ctx._select_set
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
return null;
|
|
1421
1213
|
});
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
if (dtData._aSortData !== null) {
|
|
1472
|
-
dtData._aSortData[i] = null;
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
});
|
|
1477
|
-
|
|
1478
|
-
this.iterator('table', function (ct) {
|
|
1479
|
-
eventTrigger(api, 'select', ['row', selectedIndexes], true);
|
|
1480
|
-
});
|
|
1481
|
-
|
|
1482
|
-
return this;
|
|
1214
|
+
DataTable.Api.registerPlural('rows().select()', 'row().select()', function (select = true) {
|
|
1215
|
+
var api = this;
|
|
1216
|
+
var selectedIndexes = [];
|
|
1217
|
+
if (select === false) {
|
|
1218
|
+
return this.deselect();
|
|
1219
|
+
}
|
|
1220
|
+
this.iterator('row', function (ctx, idx) {
|
|
1221
|
+
clear(ctx);
|
|
1222
|
+
// There is a good amount of knowledge of DataTables internals in
|
|
1223
|
+
// this function. It _could_ be done without that, but it would hurt
|
|
1224
|
+
// performance (or DT would need new APIs for this work)
|
|
1225
|
+
var dtData = ctx.data[idx];
|
|
1226
|
+
var dtColumns = ctx.columns;
|
|
1227
|
+
if (ctx._select.selectable) {
|
|
1228
|
+
var result = ctx._select.selectable(dtData.data, dtData.tr, idx);
|
|
1229
|
+
if (result === false) {
|
|
1230
|
+
// Not selectable - do nothing
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
Dom.s(dtData.tr).classAdd(ctx._select.className);
|
|
1235
|
+
dtData._select_selected = true;
|
|
1236
|
+
selectedIndexes.push(idx);
|
|
1237
|
+
for (var i = 0; i < dtColumns.length; i++) {
|
|
1238
|
+
var col = dtColumns[i];
|
|
1239
|
+
// Regenerate the column type if not present
|
|
1240
|
+
if (col.type === null) {
|
|
1241
|
+
api.columns().types();
|
|
1242
|
+
}
|
|
1243
|
+
if (isCheckboxColumn(col)) {
|
|
1244
|
+
var cells = dtData.cells;
|
|
1245
|
+
// Make sure the checkbox shows the right state
|
|
1246
|
+
if (cells && cells[i]) {
|
|
1247
|
+
Dom.s(cells[i])
|
|
1248
|
+
.find('input.' + checkboxClass(true))
|
|
1249
|
+
.prop('checked', true);
|
|
1250
|
+
}
|
|
1251
|
+
// Invalidate the sort data for this column, if not already
|
|
1252
|
+
// done
|
|
1253
|
+
if (dtData.orderCache !== null) {
|
|
1254
|
+
dtData.orderCache[i] = null;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
this.iterator('table', function (innerCtx) {
|
|
1260
|
+
eventTrigger(api, 'select', ['row', selectedIndexes], true);
|
|
1261
|
+
});
|
|
1262
|
+
return this;
|
|
1483
1263
|
});
|
|
1484
|
-
|
|
1485
1264
|
apiRegister('row().selected()', function () {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1265
|
+
var ctx = this.context[0];
|
|
1266
|
+
if (ctx &&
|
|
1267
|
+
this.length &&
|
|
1268
|
+
ctx.data[this[0]] &&
|
|
1269
|
+
ctx.data[this[0]]._select_selected) {
|
|
1270
|
+
return true;
|
|
1271
|
+
}
|
|
1272
|
+
return false;
|
|
1493
1273
|
});
|
|
1494
|
-
|
|
1495
1274
|
apiRegister('row().focus()', function () {
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
}
|
|
1275
|
+
var ctx = this.context[0];
|
|
1276
|
+
if (ctx && this.length && ctx.data[this[0]] && ctx.data[this[0]].tr) {
|
|
1277
|
+
ctx.data[this[0]].tr.focus();
|
|
1278
|
+
}
|
|
1501
1279
|
});
|
|
1502
|
-
|
|
1503
1280
|
apiRegister('row().blur()', function () {
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
}
|
|
1281
|
+
var ctx = this.context[0];
|
|
1282
|
+
if (ctx && this.length && ctx.data[this[0]] && ctx.data[this[0]].tr) {
|
|
1283
|
+
ctx.data[this[0]].tr.blur();
|
|
1284
|
+
}
|
|
1509
1285
|
});
|
|
1510
|
-
|
|
1511
1286
|
apiRegisterPlural('columns().select()', 'column().select()', function (select) {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
column.nodes().to$().addClass(ctx._select.className);
|
|
1529
|
-
});
|
|
1530
|
-
|
|
1531
|
-
this.iterator('table', function (ctx, i) {
|
|
1532
|
-
eventTrigger(api, 'select', ['column', api[i]], true);
|
|
1533
|
-
});
|
|
1534
|
-
|
|
1535
|
-
return this;
|
|
1287
|
+
var api = this;
|
|
1288
|
+
if (select === false) {
|
|
1289
|
+
return this.deselect();
|
|
1290
|
+
}
|
|
1291
|
+
this.iterator('column', function (ctx, idx) {
|
|
1292
|
+
clear(ctx);
|
|
1293
|
+
ctx.columns[idx]._select_selected = true;
|
|
1294
|
+
var column = new DataTable.Api(ctx).column(idx);
|
|
1295
|
+
Dom.s(column.header()).classAdd(ctx._select.className);
|
|
1296
|
+
Dom.s(column.footer()).classAdd(ctx._select.className);
|
|
1297
|
+
Dom.s(column.nodes().toArray()).classAdd(ctx._select.className);
|
|
1298
|
+
});
|
|
1299
|
+
this.iterator('table', function (innerCtx, i) {
|
|
1300
|
+
eventTrigger(api, 'select', ['column', api[i]], true);
|
|
1301
|
+
});
|
|
1302
|
+
return this;
|
|
1536
1303
|
});
|
|
1537
|
-
|
|
1538
1304
|
apiRegister('column().selected()', function () {
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1305
|
+
var ctx = this.context[0];
|
|
1306
|
+
if (ctx &&
|
|
1307
|
+
this.length &&
|
|
1308
|
+
ctx.columns[this[0]] &&
|
|
1309
|
+
ctx.columns[this[0]]._select_selected) {
|
|
1310
|
+
return true;
|
|
1311
|
+
}
|
|
1312
|
+
return false;
|
|
1546
1313
|
});
|
|
1547
|
-
|
|
1548
1314
|
apiRegisterPlural('cells().select()', 'cell().select()', function (select) {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
}
|
|
1569
|
-
});
|
|
1570
|
-
|
|
1571
|
-
this.iterator('table', function (ctx, i) {
|
|
1572
|
-
eventTrigger(api, 'select', ['cell', api.cells(api[i]).indexes().toArray()], true);
|
|
1573
|
-
});
|
|
1574
|
-
|
|
1575
|
-
return this;
|
|
1315
|
+
var api = this;
|
|
1316
|
+
if (select === false) {
|
|
1317
|
+
return this.deselect();
|
|
1318
|
+
}
|
|
1319
|
+
this.iterator('cell', function (ctx, rowIdx, colIdx) {
|
|
1320
|
+
clear(ctx);
|
|
1321
|
+
var data = ctx.data[rowIdx];
|
|
1322
|
+
if (data._selected_cells === undefined) {
|
|
1323
|
+
data._selected_cells = [];
|
|
1324
|
+
}
|
|
1325
|
+
data._selected_cells[colIdx] = true;
|
|
1326
|
+
if (data.cells) {
|
|
1327
|
+
Dom.s(data.cells[colIdx]).classAdd(ctx._select.className);
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
this.iterator('table', function (innerCtx, i) {
|
|
1331
|
+
eventTrigger(api, 'select', ['cell', api.cells(api[i]).indexes().toArray()], true);
|
|
1332
|
+
});
|
|
1333
|
+
return this;
|
|
1576
1334
|
});
|
|
1577
|
-
|
|
1578
1335
|
apiRegister('cell().selected()', function () {
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
return false;
|
|
1336
|
+
var ctx = this.context[0];
|
|
1337
|
+
if (ctx && this.length) {
|
|
1338
|
+
var row = ctx.data[this[0][0].row];
|
|
1339
|
+
if (row &&
|
|
1340
|
+
row._selected_cells &&
|
|
1341
|
+
row._selected_cells[this[0][0].column]) {
|
|
1342
|
+
return true;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return false;
|
|
1590
1346
|
});
|
|
1591
|
-
|
|
1592
1347
|
apiRegisterPlural('rows().deselect()', 'row().deselect()', function () {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
this.iterator('table', function (ctx, i) {
|
|
1629
|
-
eventTrigger(api, 'deselect', ['row', api[i]], true);
|
|
1630
|
-
});
|
|
1631
|
-
|
|
1632
|
-
return this;
|
|
1348
|
+
var api = this;
|
|
1349
|
+
this.iterator('row', function (ctx, idx) {
|
|
1350
|
+
// Like the select action, this has a lot of knowledge about DT
|
|
1351
|
+
// internally
|
|
1352
|
+
var dtData = ctx.data[idx];
|
|
1353
|
+
var dtColumns = ctx.columns;
|
|
1354
|
+
Dom.s(dtData.tr).classRemove(ctx._select.className);
|
|
1355
|
+
dtData._select_selected = false;
|
|
1356
|
+
ctx._select_lastCell = null;
|
|
1357
|
+
for (var i = 0; i < dtColumns.length; i++) {
|
|
1358
|
+
var col = dtColumns[i];
|
|
1359
|
+
// Regenerate the column type if not present
|
|
1360
|
+
if (col.type === null) {
|
|
1361
|
+
api.columns().types();
|
|
1362
|
+
}
|
|
1363
|
+
if (isCheckboxColumn(col)) {
|
|
1364
|
+
var cells = dtData.cells;
|
|
1365
|
+
// Make sure the checkbox shows the right state
|
|
1366
|
+
if (cells && cells[i]) {
|
|
1367
|
+
Dom.s(dtData.cells[i])
|
|
1368
|
+
.find('input.' + checkboxClass(true))
|
|
1369
|
+
.prop('checked', false);
|
|
1370
|
+
}
|
|
1371
|
+
// Invalidate the sort data for this column, if not already done
|
|
1372
|
+
if (dtData.orderCache !== null) {
|
|
1373
|
+
dtData.orderCache[i] = null;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
});
|
|
1378
|
+
this.iterator('table', function (ctx, i) {
|
|
1379
|
+
eventTrigger(api, 'deselect', ['row', api[i]], true);
|
|
1380
|
+
});
|
|
1381
|
+
return this;
|
|
1633
1382
|
});
|
|
1634
|
-
|
|
1635
1383
|
apiRegisterPlural('columns().deselect()', 'column().deselect()', function () {
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
this.iterator('table', function (ctx, i) {
|
|
1663
|
-
eventTrigger(api, 'deselect', ['column', api[i]], true);
|
|
1664
|
-
});
|
|
1665
|
-
|
|
1666
|
-
return this;
|
|
1384
|
+
var api = this;
|
|
1385
|
+
this.iterator('column', function (ctx, idx) {
|
|
1386
|
+
ctx.columns[idx]._select_selected = false;
|
|
1387
|
+
var api = new DataTable.Api(ctx);
|
|
1388
|
+
var column = api.column(idx);
|
|
1389
|
+
Dom.s(column.header()).classRemove(ctx._select.className);
|
|
1390
|
+
Dom.s(column.footer()).classRemove(ctx._select.className);
|
|
1391
|
+
// Need to loop over each cell, rather than just using
|
|
1392
|
+
// `column().nodes()` as cells which are individually selected should
|
|
1393
|
+
// not have the `selected` class removed from them
|
|
1394
|
+
api.cells(null, idx)
|
|
1395
|
+
.indexes()
|
|
1396
|
+
.each(function (cellIdx) {
|
|
1397
|
+
var data = ctx.data[cellIdx.row];
|
|
1398
|
+
var cellSelected = data._selected_cells;
|
|
1399
|
+
if (data.cells &&
|
|
1400
|
+
(!cellSelected || !cellSelected[cellIdx.column])) {
|
|
1401
|
+
Dom.s(data.cells[cellIdx.column]).classRemove(ctx._select.className);
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
});
|
|
1405
|
+
this.iterator('table', function (ctx, i) {
|
|
1406
|
+
eventTrigger(api, 'deselect', ['column', api[i]], true);
|
|
1407
|
+
});
|
|
1408
|
+
return this;
|
|
1667
1409
|
});
|
|
1668
|
-
|
|
1669
1410
|
apiRegisterPlural('cells().deselect()', 'cell().deselect()', function () {
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
this.iterator('table', function (ctx, i) {
|
|
1688
|
-
eventTrigger(api, 'deselect', ['cell', api[i]], true);
|
|
1689
|
-
});
|
|
1690
|
-
|
|
1691
|
-
return this;
|
|
1411
|
+
var api = this;
|
|
1412
|
+
this.iterator('cell', function (ctx, rowIdx, colIdx) {
|
|
1413
|
+
var data = ctx.data[rowIdx];
|
|
1414
|
+
if (data._selected_cells !== undefined) {
|
|
1415
|
+
data._selected_cells[colIdx] = false;
|
|
1416
|
+
}
|
|
1417
|
+
// Remove class only if the cells exist, and the cell is not column
|
|
1418
|
+
// selected, in which case the class should remain (since it is selected
|
|
1419
|
+
// in the column)
|
|
1420
|
+
if (data.cells && !ctx.columns[colIdx]._select_selected) {
|
|
1421
|
+
Dom.s(data.cells[colIdx]).classRemove(ctx._select.className);
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
this.iterator('table', function (ctx, i) {
|
|
1425
|
+
eventTrigger(api, 'deselect', ['cell', api[i]], true);
|
|
1426
|
+
});
|
|
1427
|
+
return this;
|
|
1692
1428
|
});
|
|
1693
|
-
|
|
1694
1429
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
1695
1430
|
* Buttons
|
|
1696
1431
|
*/
|
|
1697
1432
|
function i18n(label, def) {
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1433
|
+
return function (dt) {
|
|
1434
|
+
return dt.i18n('buttons.' + label, def);
|
|
1435
|
+
};
|
|
1701
1436
|
}
|
|
1702
|
-
|
|
1703
1437
|
// Common events with suitable namespaces
|
|
1704
1438
|
function namespacedEvents(config) {
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1439
|
+
var unique = config._eventNamespace;
|
|
1440
|
+
return ('draw.dt.DT' +
|
|
1441
|
+
unique +
|
|
1442
|
+
' select.dt.DT' +
|
|
1443
|
+
unique +
|
|
1444
|
+
' deselect.dt.DT' +
|
|
1445
|
+
unique);
|
|
1708
1446
|
}
|
|
1709
|
-
|
|
1710
1447
|
function enabled(dt, config) {
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1448
|
+
if (config.limitTo.indexOf('rows') !== -1 &&
|
|
1449
|
+
dt.rows({ selected: true }).any()) {
|
|
1450
|
+
return true;
|
|
1451
|
+
}
|
|
1452
|
+
if (config.limitTo.indexOf('columns') !== -1 &&
|
|
1453
|
+
dt.columns({ selected: true }).any()) {
|
|
1454
|
+
return true;
|
|
1455
|
+
}
|
|
1456
|
+
if (config.limitTo.indexOf('cells') !== -1 &&
|
|
1457
|
+
dt.cells({ selected: true }).any()) {
|
|
1458
|
+
return true;
|
|
1459
|
+
}
|
|
1460
|
+
return false;
|
|
1724
1461
|
}
|
|
1725
|
-
|
|
1726
1462
|
var _buttonNamespace = 0;
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
// Use a fixed filtering function to match on selected rows
|
|
1828
|
-
// This needs to reference the internal aoData since that is
|
|
1829
|
-
// where Select stores its reference for the selected state
|
|
1830
|
-
var dataSrc = dt.settings()[0].aoData;
|
|
1831
|
-
|
|
1832
|
-
dt.search.fixed('dt-select', function (text, data, idx) {
|
|
1833
|
-
// _select_selected is set by Select on the data object for the row
|
|
1834
|
-
return dataSrc[idx]._select_selected;
|
|
1835
|
-
});
|
|
1836
|
-
|
|
1837
|
-
this.active(true);
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
dt.draw();
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1463
|
+
util.object.assign(DataTable.ext.buttons, {
|
|
1464
|
+
selected: {
|
|
1465
|
+
text: i18n('selected', 'Selected'),
|
|
1466
|
+
className: 'buttons-selected',
|
|
1467
|
+
limitTo: ['rows', 'columns', 'cells'],
|
|
1468
|
+
init: function (dt, node, config) {
|
|
1469
|
+
var that = this;
|
|
1470
|
+
config._eventNamespace = '.select' + _buttonNamespace++;
|
|
1471
|
+
// .DT namespace listeners are removed by DataTables automatically
|
|
1472
|
+
// on table destroy
|
|
1473
|
+
dt.on(namespacedEvents(config), function () {
|
|
1474
|
+
that.enable(enabled(dt, config));
|
|
1475
|
+
});
|
|
1476
|
+
this.disable();
|
|
1477
|
+
},
|
|
1478
|
+
destroy: function (dt, node, config) {
|
|
1479
|
+
dt.off(config._eventNamespace);
|
|
1480
|
+
}
|
|
1481
|
+
},
|
|
1482
|
+
selectedSingle: {
|
|
1483
|
+
text: i18n('selectedSingle', 'Selected single'),
|
|
1484
|
+
className: 'buttons-selected-single',
|
|
1485
|
+
init: function (dt, node, config) {
|
|
1486
|
+
var that = this;
|
|
1487
|
+
config._eventNamespace = '.select' + _buttonNamespace++;
|
|
1488
|
+
dt.on(namespacedEvents(config), function () {
|
|
1489
|
+
var count = dt.rows({ selected: true }).flatten().length +
|
|
1490
|
+
dt.columns({ selected: true }).flatten().length +
|
|
1491
|
+
dt.cells({ selected: true }).flatten().length;
|
|
1492
|
+
that.enable(count === 1);
|
|
1493
|
+
});
|
|
1494
|
+
this.disable();
|
|
1495
|
+
},
|
|
1496
|
+
destroy: function (dt, node, config) {
|
|
1497
|
+
dt.off(config._eventNamespace);
|
|
1498
|
+
}
|
|
1499
|
+
},
|
|
1500
|
+
selectAll: {
|
|
1501
|
+
text: i18n('selectAll', 'Select all'),
|
|
1502
|
+
className: 'buttons-select-all',
|
|
1503
|
+
action: function (e, dt, node, config) {
|
|
1504
|
+
var items = this.select.items();
|
|
1505
|
+
var mod = config.selectorModifier;
|
|
1506
|
+
if (mod) {
|
|
1507
|
+
if (typeof mod === 'function') {
|
|
1508
|
+
mod = mod.call(dt, e, dt, node, config);
|
|
1509
|
+
}
|
|
1510
|
+
this[items + 's'](mod).select();
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
this[items + 's']().select();
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
// selectorModifier can be specified
|
|
1517
|
+
},
|
|
1518
|
+
selectNone: {
|
|
1519
|
+
text: i18n('selectNone', 'Deselect all'),
|
|
1520
|
+
className: 'buttons-select-none',
|
|
1521
|
+
action: function () {
|
|
1522
|
+
clear(this.settings()[0], true);
|
|
1523
|
+
},
|
|
1524
|
+
init: function (dt, node, config) {
|
|
1525
|
+
var that = this;
|
|
1526
|
+
config._eventNamespace = '.select' + _buttonNamespace++;
|
|
1527
|
+
dt.on(namespacedEvents(config), function () {
|
|
1528
|
+
var count = dt.rows({ selected: true }).flatten().length +
|
|
1529
|
+
dt.columns({ selected: true }).flatten().length +
|
|
1530
|
+
dt.cells({ selected: true }).flatten().length;
|
|
1531
|
+
that.enable(count > 0);
|
|
1532
|
+
});
|
|
1533
|
+
this.disable();
|
|
1534
|
+
},
|
|
1535
|
+
destroy: function (dt, node, config) {
|
|
1536
|
+
dt.off(config._eventNamespace);
|
|
1537
|
+
}
|
|
1538
|
+
},
|
|
1539
|
+
showSelected: {
|
|
1540
|
+
text: i18n('showSelected', 'Show only selected'),
|
|
1541
|
+
className: 'buttons-show-selected',
|
|
1542
|
+
action: function (e, dt) {
|
|
1543
|
+
if (dt.search.fixed('dt-select')) {
|
|
1544
|
+
// Remove existing function
|
|
1545
|
+
dt.search.fixed('dt-select', null);
|
|
1546
|
+
this.active(false);
|
|
1547
|
+
}
|
|
1548
|
+
else {
|
|
1549
|
+
// Use a fixed filtering function to match on selected rows
|
|
1550
|
+
// This needs to reference the internal data since that is
|
|
1551
|
+
// where Select stores its reference for the selected state
|
|
1552
|
+
var dataSrc = dt.settings()[0].data;
|
|
1553
|
+
dt.search.fixed('dt-select', function (text, data, idx) {
|
|
1554
|
+
// _select_selected is set by Select on the data object for
|
|
1555
|
+
// the row
|
|
1556
|
+
return dataSrc[idx]._select_selected;
|
|
1557
|
+
});
|
|
1558
|
+
this.active(true);
|
|
1559
|
+
}
|
|
1560
|
+
dt.draw();
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1843
1563
|
});
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
that.active(items === lc);
|
|
1861
|
-
});
|
|
1862
|
-
}
|
|
1863
|
-
};
|
|
1564
|
+
['Row', 'Column', 'Cell'].forEach(function (item) {
|
|
1565
|
+
var lc = item.toLowerCase();
|
|
1566
|
+
DataTable.ext.buttons['select' + item + 's'] = {
|
|
1567
|
+
text: i18n('select' + item + 's', 'Select ' + lc + 's'),
|
|
1568
|
+
className: 'buttons-select-' + lc + 's',
|
|
1569
|
+
action: function () {
|
|
1570
|
+
this.select.items(lc);
|
|
1571
|
+
},
|
|
1572
|
+
init: function (dt) {
|
|
1573
|
+
var that = this;
|
|
1574
|
+
this.active(dt.select.items() === lc);
|
|
1575
|
+
dt.on('selectItems.dt.DT', function (e, ctx, items) {
|
|
1576
|
+
that.active(items === lc);
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1864
1580
|
});
|
|
1865
|
-
|
|
1866
|
-
// Note that DataTables 2.1 has more robust type detection, but we retain
|
|
1867
|
-
// backwards compatibility with 2.0 for the moment.
|
|
1868
1581
|
DataTable.type('select-checkbox', {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
order: {
|
|
1887
|
-
pre: function (d) {
|
|
1888
|
-
return d === 'X' ? -1 : 0;
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1582
|
+
className: 'dt-select',
|
|
1583
|
+
detect: {
|
|
1584
|
+
oneOf: function () {
|
|
1585
|
+
return false; // no op
|
|
1586
|
+
},
|
|
1587
|
+
allOf: function () {
|
|
1588
|
+
return false; // no op
|
|
1589
|
+
},
|
|
1590
|
+
init: function (settings, col, idx) {
|
|
1591
|
+
return isCheckboxColumn(col);
|
|
1592
|
+
}
|
|
1593
|
+
},
|
|
1594
|
+
order: {
|
|
1595
|
+
pre: function (d) {
|
|
1596
|
+
return d === 'X' ? -1 : 0;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1891
1599
|
});
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
}
|
|
1600
|
+
util.object.assignDeep(DataTable.defaults.language, {
|
|
1601
|
+
select: {
|
|
1602
|
+
aria: {
|
|
1603
|
+
rowCheckbox: 'Select row'
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1899
1606
|
});
|
|
1900
|
-
|
|
1901
1607
|
DataTable.render.select = function (valueProp, nameProp) {
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
// Workaround so uglify doesn't strip the function name. It is used
|
|
1951
|
-
// for the column type detection.
|
|
1952
|
-
fn._name = 'selectCheckbox';
|
|
1953
|
-
|
|
1954
|
-
return fn;
|
|
1955
|
-
}
|
|
1956
|
-
|
|
1608
|
+
var valueFn = valueProp ? DataTable.util.get(valueProp) : null;
|
|
1609
|
+
var nameFn = nameProp ? DataTable.util.get(nameProp) : null;
|
|
1610
|
+
var fn = function (data, type, row, meta) {
|
|
1611
|
+
var dtRow = meta.settings.data[meta.row];
|
|
1612
|
+
var selected = dtRow._select_selected;
|
|
1613
|
+
var ariaLabel = meta.settings.language.select.aria.rowCheckbox;
|
|
1614
|
+
var selectable = meta.settings._select.selectable;
|
|
1615
|
+
var selectedClass = meta.settings._select.className;
|
|
1616
|
+
if (type === 'display') {
|
|
1617
|
+
// Check if the row is selectable before showing the checkbox
|
|
1618
|
+
if (selectable) {
|
|
1619
|
+
var result = selectable(row, dtRow.tr, meta.row);
|
|
1620
|
+
if (result === false) {
|
|
1621
|
+
return '';
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
return Dom.c('input')
|
|
1625
|
+
.attr({
|
|
1626
|
+
'aria-label': ariaLabel,
|
|
1627
|
+
class: checkboxClass(false),
|
|
1628
|
+
name: nameFn ? nameFn(row) : null,
|
|
1629
|
+
type: 'checkbox',
|
|
1630
|
+
value: valueFn ? valueFn(row) : null,
|
|
1631
|
+
checked: selected
|
|
1632
|
+
})
|
|
1633
|
+
.on('input', function (e) {
|
|
1634
|
+
// Let Select 100% cotrol the state of the checkbox
|
|
1635
|
+
e.preventDefault();
|
|
1636
|
+
// And make sure this checkbox matches it's row as it is
|
|
1637
|
+
// possible to check out of sync if this was clicked on to
|
|
1638
|
+
// deselect a range but remains selected itself
|
|
1639
|
+
Dom.s(this).prop('checked', Dom.s(this).closest('tr').classHas(selectedClass));
|
|
1640
|
+
})
|
|
1641
|
+
.get(0);
|
|
1642
|
+
}
|
|
1643
|
+
else if (type === 'type') {
|
|
1644
|
+
return 'select-checkbox';
|
|
1645
|
+
}
|
|
1646
|
+
else if (type === 'filter') {
|
|
1647
|
+
return '';
|
|
1648
|
+
}
|
|
1649
|
+
return selected ? 'X' : '';
|
|
1650
|
+
};
|
|
1651
|
+
// Workaround so uglify doesn't strip the function name. It is used
|
|
1652
|
+
// for the column type detection.
|
|
1653
|
+
fn._name = 'selectCheckbox';
|
|
1654
|
+
return fn;
|
|
1655
|
+
};
|
|
1957
1656
|
// Legacy checkbox ordering
|
|
1958
1657
|
DataTable.ext.order['select-checkbox'] = function (settings, col) {
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1658
|
+
return this.api()
|
|
1659
|
+
.column(col, { order: 'index' })
|
|
1660
|
+
.nodes()
|
|
1661
|
+
.map(function (td) {
|
|
1662
|
+
if (settings._select.items === 'row') {
|
|
1663
|
+
return Dom.s(td)
|
|
1664
|
+
.parent()
|
|
1665
|
+
.classHas(settings._select.className)
|
|
1666
|
+
.toString();
|
|
1667
|
+
}
|
|
1668
|
+
else if (settings._select.items === 'cell') {
|
|
1669
|
+
return Dom.s(td)
|
|
1670
|
+
.classHas(settings._select.className)
|
|
1671
|
+
.toString();
|
|
1672
|
+
}
|
|
1673
|
+
return false;
|
|
1674
|
+
});
|
|
1971
1675
|
};
|
|
1972
|
-
|
|
1973
|
-
$.fn.DataTable.select = DataTable.select;
|
|
1974
|
-
|
|
1975
1676
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
1976
1677
|
* Initialisation
|
|
1977
1678
|
*/
|
|
1978
|
-
|
|
1979
1679
|
// DataTables creation - we need this to run _before_ data is read in, but
|
|
1980
1680
|
// for backwards compat. we also run again on preInit. If it happens twice
|
|
1981
1681
|
// it will simply do nothing the second time around.
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
DataTable.select.init(new DataTable.Api(ctx));
|
|
1682
|
+
Dom.s(document).on('i18n.dt.dtSelect preInit.dt.dtSelect', function (e, ctx) {
|
|
1683
|
+
if (e.namespace !== 'dt') {
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
DataTable.select.init(new DataTable.Api(ctx));
|
|
1988
1687
|
});
|
|
1989
1688
|
|
|
1990
1689
|
|
|
1991
1690
|
export default DataTable;
|
|
1691
|
+
|