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