aa-intel-tool 2.12.1__py3-none-any.whl → 2.13.0__py3-none-any.whl
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.
- aa_intel_tool/__init__.py +1 -1
- aa_intel_tool/locale/cs_CZ/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/de/LC_MESSAGES/django.mo +0 -0
- aa_intel_tool/locale/de/LC_MESSAGES/django.po +5 -5
- aa_intel_tool/locale/django.pot +2 -2
- aa_intel_tool/locale/es/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/fr_FR/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/it_IT/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/ja/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/ko_KR/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/nl_NL/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/pl_PL/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/ru/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/sk/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/uk/LC_MESSAGES/django.po +1 -1
- aa_intel_tool/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- aa_intel_tool/locale/zh_Hans/LC_MESSAGES/django.po +6 -5
- aa_intel_tool/templates/aa_intel_tool/views/scan/chatlist.html +4 -2
- aa_intel_tool/templates/aa_intel_tool/views/scan/dscan.html +4 -2
- aa_intel_tool/templates/aa_intel_tool/views/scan/fleetcomp.html +4 -2
- {aa_intel_tool-2.12.1.dist-info → aa_intel_tool-2.13.0.dist-info}/METADATA +2 -2
- {aa_intel_tool-2.12.1.dist-info → aa_intel_tool-2.13.0.dist-info}/RECORD +24 -52
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.css +0 -610
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.js +0 -123
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.min.css +0 -8
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.min.css.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.min.js +0 -6
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/dataTables.bootstrap5.min.js.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/datatables.min.js +0 -10
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/2.3.4/datatables.min.js.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.css +0 -516
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.min.css +0 -2
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.min.css.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.js +0 -73
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.min.js +0 -6
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.min.js.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.js +0 -3091
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.min.js +0 -10
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.min.js.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.css +0 -20
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.min.css +0 -2
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.min.css.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.js +0 -1203
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.min.js +0 -6
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.min.js.map +0 -1
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.js +0 -59
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.min.js +0 -6
- aa_intel_tool/static/aa_intel_tool/libs/DataTables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.min.js.map +0 -1
- aa_intel_tool/templates/aa_intel_tool/bundles/datatables-2-css.html +0 -11
- aa_intel_tool/templates/aa_intel_tool/bundles/datatables-2-js.html +0 -14
- {aa_intel_tool-2.12.1.dist-info → aa_intel_tool-2.13.0.dist-info}/WHEEL +0 -0
- {aa_intel_tool-2.12.1.dist-info → aa_intel_tool-2.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,3091 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* ColumnControl 1.1.1
|
|
3
|
-
* Copyright (c) SpryMedia Ltd - datatables.net/license
|
|
4
|
-
*
|
|
5
|
-
* SVG icons: ISC License
|
|
6
|
-
* Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT).
|
|
7
|
-
* All other copyright (c) for Lucide are held by Lucide Contributors 2022.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
(function( factory ){
|
|
11
|
-
if ( typeof define === 'function' && define.amd ) {
|
|
12
|
-
// AMD
|
|
13
|
-
define( ['jquery', 'datatables.net'], function ( $ ) {
|
|
14
|
-
return factory( $, window, document );
|
|
15
|
-
} );
|
|
16
|
-
}
|
|
17
|
-
else if ( typeof exports === 'object' ) {
|
|
18
|
-
// CommonJS
|
|
19
|
-
var jq = require('jquery');
|
|
20
|
-
var cjsRequires = function (root, $) {
|
|
21
|
-
if ( ! $.fn.dataTable ) {
|
|
22
|
-
require('datatables.net')(root, $);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
if (typeof window === 'undefined') {
|
|
27
|
-
module.exports = function (root, $) {
|
|
28
|
-
if ( ! root ) {
|
|
29
|
-
// CommonJS environments without a window global must pass a
|
|
30
|
-
// root. This will give an error otherwise
|
|
31
|
-
root = window;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if ( ! $ ) {
|
|
35
|
-
$ = jq( root );
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
cjsRequires( root, $ );
|
|
39
|
-
return factory( $, root, root.document );
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
cjsRequires( window, jq );
|
|
44
|
-
module.exports = factory( jq, window, window.document );
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// Browser
|
|
49
|
-
factory( jQuery, window, document );
|
|
50
|
-
}
|
|
51
|
-
}(function( $, window, document ) {
|
|
52
|
-
'use strict';
|
|
53
|
-
var DataTable = $.fn.dataTable;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
function createElement(type, classes, text, children) {
|
|
58
|
-
if (classes === void 0) { classes = []; }
|
|
59
|
-
if (text === void 0) { text = null; }
|
|
60
|
-
if (children === void 0) { children = []; }
|
|
61
|
-
var el = document.createElement(type);
|
|
62
|
-
addClass(el, classes);
|
|
63
|
-
if (text) {
|
|
64
|
-
el.innerHTML = text;
|
|
65
|
-
}
|
|
66
|
-
children.forEach(function (child) {
|
|
67
|
-
el.appendChild(child);
|
|
68
|
-
});
|
|
69
|
-
return el;
|
|
70
|
-
}
|
|
71
|
-
function addClass(el, classes) {
|
|
72
|
-
if (!classes) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (!Array.isArray(classes)) {
|
|
76
|
-
classes = [classes];
|
|
77
|
-
}
|
|
78
|
-
classes.forEach(function (className) {
|
|
79
|
-
if (el && className) {
|
|
80
|
-
el.classList.add(className);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// The SVG for many of these icons are from Lucide ( https://lucide.dev ), which are available
|
|
86
|
-
// under the ISC License. There are a number of custom icons as well. These are optimised through
|
|
87
|
-
// https://optimize.svgomg.net/
|
|
88
|
-
function wrap(paths) {
|
|
89
|
-
return ('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
|
|
90
|
-
paths +
|
|
91
|
-
'</svg>');
|
|
92
|
-
}
|
|
93
|
-
var icons = {
|
|
94
|
-
chevronRight: wrap('<path d="m9 18 6-6-6-6"/>'),
|
|
95
|
-
// columns-3
|
|
96
|
-
columns: wrap('<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/><path d="M15 3v18"/>'),
|
|
97
|
-
// Custom
|
|
98
|
-
contains: wrap('<path d="M10 3h4v18h-4z"/><path d="M18 8h3v9h-3"/><path d="M6 17H3V8h3"/>'),
|
|
99
|
-
empty: wrap('<circle cx="12" cy="12" r="10"/>'),
|
|
100
|
-
ends: wrap('<path d="M21 3h-4v18h4z"/><path d="M13 8H3v9h10"/>'),
|
|
101
|
-
// Customised
|
|
102
|
-
equal: wrap('<line x1="5" x2="19" y1="9" y2="9"/><line x1="5" x2="19" y1="15" y2="15"/>'),
|
|
103
|
-
greater: wrap('<path d="m9 18 6-6-6-6"/>'),
|
|
104
|
-
// Custom
|
|
105
|
-
greaterOrEqual: wrap('<path d="m9 16 6-6-6-6"/><path d="m9 21 6-6"/>'),
|
|
106
|
-
// Custom
|
|
107
|
-
groupAdd: wrap('<path d="M6 21v-7.5m-3.549 3.75H9.75"/><rect width="13.5" height="7.5" x="3" y="3" rx="1.5"/><rect width="7.5" height="7.5" x="13.5" y="13.5" fill="currentColor" rx="1.5"/>'),
|
|
108
|
-
// Custom
|
|
109
|
-
groupClear: wrap('<rect width="13.5" height="7.5" x="3" y="3" rx="1.5"/><rect width="7.5" height="7.5" x="13.5" y="13.5" rx="1.5"/>'),
|
|
110
|
-
// Custom
|
|
111
|
-
groupTop: wrap('<rect width="13.5" height="7.5" x="3" y="3" fill="currentColor" rx="1.5"/><rect width="7.5" height="7.5" x="13.5" y="13.5" rx="1.5"/>'),
|
|
112
|
-
// Custom
|
|
113
|
-
groupRemove: wrap('<path d="M2.451 17.25H9.75"/><rect width="13.5" height="7.5" x="3" y="3" rx="1.5"/><rect width="7.5" height="7.5" x="13.5" y="13.5" rx="1.5"/>'),
|
|
114
|
-
less: wrap('<path d="m15 18-6-6 6-6"/>'),
|
|
115
|
-
// Custom
|
|
116
|
-
lessOrEqual: wrap('<path d="m15 16-6-6 6-6"/><path d="m15 21-6-6"/>'),
|
|
117
|
-
menu: wrap('<line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/>'),
|
|
118
|
-
// move-horizontal
|
|
119
|
-
move: wrap('<line x1="12" x2="12" y1="3" y2="21"/><polyline points="8 8 4 12 8 16"/><polyline points="16 16 20 12 16 8"/>'),
|
|
120
|
-
// arrow-left-from-line
|
|
121
|
-
moveLeft: wrap('<path d="m9 6-6 6 6 6"/><path d="M3 12h14"/><path d="M21 19V5"/>'),
|
|
122
|
-
// arrow-right-from-line
|
|
123
|
-
moveRight: wrap('<path d="M3 5v14"/><path d="M21 12H7"/><path d="m15 18 6-6-6-6"/>'),
|
|
124
|
-
// Custom
|
|
125
|
-
notContains: wrap('<path d="M15 4 9 20"/><path d="M3 8h18v9H3z"/>'),
|
|
126
|
-
notEmpty: wrap('<circle cx="12" cy="12" r="10"/><line x1="9" x2="15" y1="15" y2="9"/>'),
|
|
127
|
-
notEqual: wrap('<path d="M5 9h14"/><path d="M5 15h14"/><path d="M15 5 9 19"/>'),
|
|
128
|
-
// Custom
|
|
129
|
-
orderAddAsc: wrap('<path d="M17 21v-8"/><path d="M3 4h6"/><path d="M3 8h9"/><path d="M3 12h10"/><path d="M13 17h8"/>'),
|
|
130
|
-
// Custom
|
|
131
|
-
orderAddDesc: wrap('<path d="M17 21v-8"/><path d="M3 4h12"/><path d="M3 8h9"/><path d="M3 12h6"/><path d="M13 17h8"/>'),
|
|
132
|
-
orderAsc: wrap('<path d="m3 8 4-4 4 4"/><path d="M7 4v16"/><path d="M11 12h4"/><path d="M11 16h7"/><path d="M11 20h10"/>'),
|
|
133
|
-
// Custom
|
|
134
|
-
orderClear: wrap('<path d="m21 21-8-8"/><path d="M3 4h12"/><path d="M3 8h9"/><path d="M3 12h6"/><path d="m13 21 8-8"/>'),
|
|
135
|
-
orderDesc: wrap('<path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="M11 4h10"/><path d="M11 8h7"/><path d="M11 12h4"/>'),
|
|
136
|
-
// Custom
|
|
137
|
-
orderRemove: wrap('<path d="M3 4h12"/><path d="M3 8h9"/><path d="M3 12h6"/><path d="M13 17h8"/>'),
|
|
138
|
-
// Custom
|
|
139
|
-
orderNone: wrap('<path d="m3 8 4-4 4 4"/><path d="m11 16-4 4-4-4"/><path d="M7 4v16"/><path d="M15 8h6"/><path d="M15 16h6"/><path d="M13 12h8"/>'),
|
|
140
|
-
// search
|
|
141
|
-
search: wrap('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),
|
|
142
|
-
// search-x
|
|
143
|
-
searchClear: wrap('<path d="m13.5 8.5-5 5"/><path d="m8.5 8.5 5 5"/><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),
|
|
144
|
-
// Custom
|
|
145
|
-
starts: wrap('<path d="M3 3h4v18H3z"/><path d="M11 8h10v9H11"/>'),
|
|
146
|
-
// tick
|
|
147
|
-
tick: wrap('<path d="M20 6 9 17l-5-5"/>'),
|
|
148
|
-
// x
|
|
149
|
-
x: wrap('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>')
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Close all or only other dropdowns
|
|
154
|
-
*
|
|
155
|
-
* @param e Event or null to close all others
|
|
156
|
-
*/
|
|
157
|
-
function close(e) {
|
|
158
|
-
if (e === void 0) { e = null; }
|
|
159
|
-
document.querySelectorAll('div.dtcc-dropdown').forEach(function (el) {
|
|
160
|
-
if (e === null || !el.contains(e.target)) {
|
|
161
|
-
el._close();
|
|
162
|
-
if (!e._closed) {
|
|
163
|
-
e._closed = [];
|
|
164
|
-
}
|
|
165
|
-
e._closed.push(el);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
function getContainer(dt, btn) {
|
|
170
|
-
return btn.closest('div.dtfh-floatingparent') || dt.table().container();
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Position the dropdown relative to the button that activated it, with possible corrections
|
|
174
|
-
* to make sure it is visible on the page.
|
|
175
|
-
*
|
|
176
|
-
* @param dropdown Dropdown element
|
|
177
|
-
* @param dt Container DataTable
|
|
178
|
-
* @param btn Button the dropdown emanates from
|
|
179
|
-
*/
|
|
180
|
-
function positionDropdown(dropdown, dt, btn) {
|
|
181
|
-
var header = btn.closest('div.dt-column-header');
|
|
182
|
-
var container = getContainer(dt, btn);
|
|
183
|
-
var headerStyle = getComputedStyle(header);
|
|
184
|
-
var dropdownWidth = dropdown.offsetWidth;
|
|
185
|
-
var position = relativePosition(container, btn);
|
|
186
|
-
var left, top;
|
|
187
|
-
top = position.top + btn.offsetHeight;
|
|
188
|
-
if (headerStyle.flexDirection === 'row-reverse') {
|
|
189
|
-
// Icon is on the left of the header - align the left hand sides
|
|
190
|
-
left = position.left;
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// Icon is on the right of the header - align the right hand sides
|
|
194
|
-
left = position.left - dropdownWidth + btn.offsetWidth;
|
|
195
|
-
}
|
|
196
|
-
// Corrections - don't extend past the DataTable to the left and right
|
|
197
|
-
var containerWidth = container.offsetWidth;
|
|
198
|
-
if (left + dropdownWidth > containerWidth) {
|
|
199
|
-
left -= left + dropdownWidth - containerWidth;
|
|
200
|
-
}
|
|
201
|
-
if (left < 0) {
|
|
202
|
-
left = 0;
|
|
203
|
-
}
|
|
204
|
-
dropdown.style.top = top + 'px';
|
|
205
|
-
dropdown.style.left = left + 'px';
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Display the dropdown in the document
|
|
209
|
-
*
|
|
210
|
-
* @param dropdown Dropdown element
|
|
211
|
-
* @param dt Container DataTable
|
|
212
|
-
* @param btn Button the dropdown emanates from
|
|
213
|
-
* @returns Function to call when the dropdown should be removed from the document
|
|
214
|
-
*/
|
|
215
|
-
function attachDropdown(dropdown, dt, btn) {
|
|
216
|
-
var dtContainer = getContainer(dt, btn.element());
|
|
217
|
-
dropdown._shown = true;
|
|
218
|
-
dtContainer.append(dropdown);
|
|
219
|
-
positionDropdown(dropdown, dt, btn.element());
|
|
220
|
-
btn.element().setAttribute('aria-expanded', 'true');
|
|
221
|
-
// Note that this could be called when the dropdown has already been removed from the document
|
|
222
|
-
// via another dropdown being shown. This will clean up the event on the next body click.
|
|
223
|
-
var removeDropdown = function (e) {
|
|
224
|
-
// Not in document, so just clean up the event handler
|
|
225
|
-
if (!dropdown._shown) {
|
|
226
|
-
document.body.removeEventListener('click', removeDropdown);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
// If the click is inside the dropdown, ignore it - we don't want to immediately close
|
|
230
|
-
if (e.target === dropdown || dropdown.contains(e.target)) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
// If there is currently a datetime picker visible on the page, assume that it belongs to
|
|
234
|
-
// this dropdown. Don't want to close while operating on the picker.
|
|
235
|
-
var datetime = document.querySelector('div.dt-datetime');
|
|
236
|
-
if (datetime && (e.target === datetime || datetime.contains(e.target))) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
dropdown._close();
|
|
240
|
-
document.body.removeEventListener('click', removeDropdown);
|
|
241
|
-
};
|
|
242
|
-
document.body.addEventListener('click', removeDropdown);
|
|
243
|
-
return removeDropdown;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Get the position of an element, relative to a given parent. The origin MUST be under the
|
|
247
|
-
* parent's tree.
|
|
248
|
-
*
|
|
249
|
-
* @param parent Parent element to get position relative to
|
|
250
|
-
* @param origin Target element
|
|
251
|
-
*/
|
|
252
|
-
function relativePosition(parent, origin) {
|
|
253
|
-
var top = 0;
|
|
254
|
-
var left = 0;
|
|
255
|
-
while (origin && origin !== parent && origin !== document.body) {
|
|
256
|
-
top += origin.offsetTop;
|
|
257
|
-
left += origin.offsetLeft;
|
|
258
|
-
if (origin.scrollTop) {
|
|
259
|
-
left -= origin.scrollTop;
|
|
260
|
-
}
|
|
261
|
-
if (origin.scrollLeft) {
|
|
262
|
-
left -= origin.scrollLeft;
|
|
263
|
-
}
|
|
264
|
-
origin = origin.offsetParent;
|
|
265
|
-
}
|
|
266
|
-
return {
|
|
267
|
-
top: top,
|
|
268
|
-
left: left
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Function that will provide the keyboard navigation for the dropdown
|
|
273
|
-
*
|
|
274
|
-
* @param dropdown Dropdown element in question
|
|
275
|
-
* @returns Function that can be bound to `keypress`
|
|
276
|
-
*/
|
|
277
|
-
function focusCapture(dropdown, host) {
|
|
278
|
-
return function (e) {
|
|
279
|
-
// Do nothing if not shown
|
|
280
|
-
if (!dropdown._shown) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
// Focus trap for tab key
|
|
284
|
-
var elements = Array.from(dropdown.querySelectorAll('a, button, input, select'));
|
|
285
|
-
var active = document.activeElement;
|
|
286
|
-
// An escape key should close the dropdown
|
|
287
|
-
if (e.key === 'Escape') {
|
|
288
|
-
dropdown._close();
|
|
289
|
-
host.focus(); // Restore focus to the host
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
else if (e.key !== 'Tab' || elements.length === 0) {
|
|
293
|
-
// Anything other than tab we aren't interested in from here
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
if (!elements.includes(active)) {
|
|
297
|
-
// If new focus is not inside the popover we want to drag it back in
|
|
298
|
-
elements[0].focus();
|
|
299
|
-
e.preventDefault();
|
|
300
|
-
}
|
|
301
|
-
else if (e.shiftKey) {
|
|
302
|
-
// Reverse tabbing order when shift key is pressed
|
|
303
|
-
if (active === elements[0]) {
|
|
304
|
-
elements[elements.length - 1].focus();
|
|
305
|
-
e.preventDefault();
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
if (active === elements[elements.length - 1]) {
|
|
310
|
-
elements[0].focus();
|
|
311
|
-
e.preventDefault();
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
var dropdownContent = {
|
|
317
|
-
classes: {
|
|
318
|
-
container: 'dtcc-dropdown',
|
|
319
|
-
liner: 'dtcc-dropdown-liner'
|
|
320
|
-
},
|
|
321
|
-
defaults: {
|
|
322
|
-
className: 'dropdown',
|
|
323
|
-
content: [],
|
|
324
|
-
icon: 'menu',
|
|
325
|
-
text: 'More...'
|
|
326
|
-
},
|
|
327
|
-
init: function (config) {
|
|
328
|
-
var dt = this.dt();
|
|
329
|
-
var dropdown = createElement('div', dropdownContent.classes.container, '', [
|
|
330
|
-
createElement('div', dropdownContent.classes.liner)
|
|
331
|
-
]);
|
|
332
|
-
dropdown._shown = false;
|
|
333
|
-
dropdown._close = function () {
|
|
334
|
-
dropdown.remove();
|
|
335
|
-
dropdown._shown = false;
|
|
336
|
-
btn.element().setAttribute('aria-expanded', 'false');
|
|
337
|
-
};
|
|
338
|
-
dropdown.setAttribute('role', 'dialog');
|
|
339
|
-
dropdown.setAttribute('aria-label', dt.i18n('columnControl.dropdown', config.text));
|
|
340
|
-
// When FixedHeader is used, the transition between states messes up positioning, so if
|
|
341
|
-
// shown we just reattach the dropdown.
|
|
342
|
-
dt.on('fixedheader-mode', function () {
|
|
343
|
-
if (dropdown._shown) {
|
|
344
|
-
attachDropdown(dropdown, dt, config._parents ? config._parents[0] : btn);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
// A liner element allows more styling options, so the contents go inside this
|
|
348
|
-
var liner = dropdown.childNodes[0];
|
|
349
|
-
var btn = new Button(dt, this)
|
|
350
|
-
.text(dt.i18n('columnControl.dropdown', config.text))
|
|
351
|
-
.icon(config.icon)
|
|
352
|
-
.className(config.className)
|
|
353
|
-
.dropdownDisplay(liner)
|
|
354
|
-
.handler(function (e) {
|
|
355
|
-
// Do nothing if our dropdown was just closed as part of the event (i.e. allow
|
|
356
|
-
// the button to toggle it closed)
|
|
357
|
-
if (e._closed && e._closed.includes(dropdown)) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
attachDropdown(dropdown, dt, config._parents ? config._parents[0] : btn);
|
|
361
|
-
// When activated using a key - auto focus on the first item in the popover
|
|
362
|
-
var focusable = dropdown.querySelector('input, a, button');
|
|
363
|
-
if (focusable && e.type === 'keypress') {
|
|
364
|
-
focusable.focus();
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
btn.element().setAttribute('aria-haspopup', 'dialog');
|
|
368
|
-
btn.element().setAttribute('aria-expanded', 'false');
|
|
369
|
-
// Add the content for the dropdown
|
|
370
|
-
for (var i = 0; i < config.content.length; i++) {
|
|
371
|
-
var content = this.resolve(config.content[i]);
|
|
372
|
-
// For nested items we need to keep a reference to the top level so the sub-levels
|
|
373
|
-
// can communicate back - e.g. active or positioned relative to that top level.
|
|
374
|
-
if (!content.config._parents) {
|
|
375
|
-
content.config._parents = [];
|
|
376
|
-
}
|
|
377
|
-
content.config._parents.push(btn);
|
|
378
|
-
var el = content.plugin.init.call(this, content.config);
|
|
379
|
-
liner.appendChild(el);
|
|
380
|
-
}
|
|
381
|
-
// For nested dropdowns, add an extra icon element to show that it will dropdown further
|
|
382
|
-
if (config._parents && config._parents.length) {
|
|
383
|
-
btn.extra('chevronRight');
|
|
384
|
-
}
|
|
385
|
-
// Reposition if needed
|
|
386
|
-
dt.on('columns-reordered', function () {
|
|
387
|
-
positionDropdown(dropdown, dt, btn.element());
|
|
388
|
-
});
|
|
389
|
-
// Focus capture events
|
|
390
|
-
var capture = focusCapture(dropdown, btn.element());
|
|
391
|
-
document.body.addEventListener('keydown', capture);
|
|
392
|
-
dt.on('destroy', function () {
|
|
393
|
-
document.body.removeEventListener('keydown', capture);
|
|
394
|
-
});
|
|
395
|
-
return btn.element();
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
var _namespace = 0;
|
|
400
|
-
var Button = /** @class */ (function () {
|
|
401
|
-
/**
|
|
402
|
-
* Create a new button for use in ColumnControl contents. Buttons created by this class can be
|
|
403
|
-
* used at the top level in the header or in a dropdown.
|
|
404
|
-
*/
|
|
405
|
-
function Button(dt, host) {
|
|
406
|
-
this._s = {
|
|
407
|
-
active: false,
|
|
408
|
-
activeList: [],
|
|
409
|
-
buttonClick: null,
|
|
410
|
-
dt: null,
|
|
411
|
-
enabled: true,
|
|
412
|
-
host: null,
|
|
413
|
-
label: '',
|
|
414
|
-
namespace: '',
|
|
415
|
-
value: null
|
|
416
|
-
};
|
|
417
|
-
this._s.dt = dt;
|
|
418
|
-
this._s.host = host;
|
|
419
|
-
this._dom = {
|
|
420
|
-
button: createElement('button', Button.classes.container),
|
|
421
|
-
dropdownDisplay: null,
|
|
422
|
-
extra: createElement('span', 'dtcc-button-extra'),
|
|
423
|
-
icon: createElement('span', 'dtcc-button-icon'),
|
|
424
|
-
state: createElement('span', 'dtcc-button-state'),
|
|
425
|
-
text: createElement('span', 'dtcc-button-text')
|
|
426
|
-
};
|
|
427
|
-
this._dom.button.setAttribute('type', 'button');
|
|
428
|
-
this._dom.button.append(this._dom.icon);
|
|
429
|
-
this._dom.button.append(this._dom.text);
|
|
430
|
-
this._dom.button.append(this._dom.state);
|
|
431
|
-
this._dom.button.append(this._dom.extra);
|
|
432
|
-
// Default state is enabled
|
|
433
|
-
this.enable(true);
|
|
434
|
-
}
|
|
435
|
-
Button.prototype.active = function (active) {
|
|
436
|
-
if (active === undefined) {
|
|
437
|
-
return this._s.active;
|
|
438
|
-
}
|
|
439
|
-
this._s.active = active;
|
|
440
|
-
this._checkActive();
|
|
441
|
-
return this;
|
|
442
|
-
};
|
|
443
|
-
/**
|
|
444
|
-
* A button can be marked as active by any of its sub-buttons (i.e. if it is a dropdown)
|
|
445
|
-
* and each one needs to be able to enable this button without effecting the active state
|
|
446
|
-
* trigged by any other sub-buttons. This method provides a way to do that.
|
|
447
|
-
*
|
|
448
|
-
* @param unique Unique id for the activate state
|
|
449
|
-
* @param active If it is active
|
|
450
|
-
* @returns Button instance
|
|
451
|
-
*/
|
|
452
|
-
Button.prototype.activeList = function (unique, active) {
|
|
453
|
-
this._s.activeList[unique] = active;
|
|
454
|
-
this._checkActive();
|
|
455
|
-
return this;
|
|
456
|
-
};
|
|
457
|
-
/**
|
|
458
|
-
* Scan over the dropdown element looking for any visible content. If there isn't any then
|
|
459
|
-
* we hide this button.
|
|
460
|
-
*
|
|
461
|
-
* @returns Button instance
|
|
462
|
-
*/
|
|
463
|
-
Button.prototype.checkDisplay = function () {
|
|
464
|
-
var visible = 0;
|
|
465
|
-
var children = this._dom.dropdownDisplay.childNodes;
|
|
466
|
-
for (var i = 0; i < children.length; i++) {
|
|
467
|
-
// No need to getComputedStyle since if a button is hidden, it was done with JS writing
|
|
468
|
-
// to style.display, so we can check against that.
|
|
469
|
-
if (children[i].style.display !== 'none') {
|
|
470
|
-
visible++;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
if (visible === 0) {
|
|
474
|
-
this._dom.button.style.display = 'none';
|
|
475
|
-
}
|
|
476
|
-
return this;
|
|
477
|
-
};
|
|
478
|
-
/**
|
|
479
|
-
* Set the class name for the button
|
|
480
|
-
*
|
|
481
|
-
* @param className Class name
|
|
482
|
-
* @returns Button instance
|
|
483
|
-
*/
|
|
484
|
-
Button.prototype.className = function (className) {
|
|
485
|
-
this._dom.button.classList.add('dtcc-button_' + className);
|
|
486
|
-
return this;
|
|
487
|
-
};
|
|
488
|
-
/**
|
|
489
|
-
* Destroy the button, cleaning up event listeners
|
|
490
|
-
*/
|
|
491
|
-
Button.prototype.destroy = function () {
|
|
492
|
-
if (this._s.buttonClick) {
|
|
493
|
-
this._dom.button.removeEventListener('click', this._s.buttonClick);
|
|
494
|
-
this._dom.button.removeEventListener('keypress', this._s.buttonClick);
|
|
495
|
-
}
|
|
496
|
-
this._s.host.destroyRemove(this);
|
|
497
|
-
};
|
|
498
|
-
/**
|
|
499
|
-
* Relevant for drop downs only. When a button in a dropdown is hidden, we might want to
|
|
500
|
-
* hide the host button as well (if it has nothing else to show). For that we need to know
|
|
501
|
-
* what the dropdown element is.
|
|
502
|
-
*
|
|
503
|
-
* @param el Element that can be used for telling us about drop down elements.
|
|
504
|
-
* @returns Button instance
|
|
505
|
-
*/
|
|
506
|
-
Button.prototype.dropdownDisplay = function (el) {
|
|
507
|
-
this._dom.dropdownDisplay = el;
|
|
508
|
-
return this;
|
|
509
|
-
};
|
|
510
|
-
/**
|
|
511
|
-
* Get the DOM Button element to attach into the document
|
|
512
|
-
*
|
|
513
|
-
* @returns The Button element
|
|
514
|
-
*/
|
|
515
|
-
Button.prototype.element = function () {
|
|
516
|
-
return this._dom.button;
|
|
517
|
-
};
|
|
518
|
-
Button.prototype.enable = function (enable) {
|
|
519
|
-
if (enable === undefined) {
|
|
520
|
-
return this._s.enabled;
|
|
521
|
-
}
|
|
522
|
-
this._dom.button.classList.toggle('dtcc-button_disabled', !enable);
|
|
523
|
-
this._s.enabled = enable;
|
|
524
|
-
return this;
|
|
525
|
-
};
|
|
526
|
-
/**
|
|
527
|
-
* Set the extra information icon
|
|
528
|
-
*
|
|
529
|
-
* @param icon Icon name
|
|
530
|
-
* @returns Button instance
|
|
531
|
-
*/
|
|
532
|
-
Button.prototype.extra = function (icon) {
|
|
533
|
-
this._dom.extra.innerHTML = icon ? icons[icon] : '';
|
|
534
|
-
return this;
|
|
535
|
-
};
|
|
536
|
-
/**
|
|
537
|
-
* Set the event handler for when the button is activated
|
|
538
|
-
*
|
|
539
|
-
* @param fn Event handler
|
|
540
|
-
* @returns Button instance
|
|
541
|
-
*/
|
|
542
|
-
Button.prototype.handler = function (fn) {
|
|
543
|
-
var _this = this;
|
|
544
|
-
var buttonClick = function (e) {
|
|
545
|
-
// Close any dropdowns which are already open
|
|
546
|
-
close(e);
|
|
547
|
-
// Stop bubbling to the DataTables default header, which might still be enabled
|
|
548
|
-
e.stopPropagation();
|
|
549
|
-
e.preventDefault();
|
|
550
|
-
if (_this._s.enabled) {
|
|
551
|
-
fn(e);
|
|
552
|
-
}
|
|
553
|
-
};
|
|
554
|
-
this._s.buttonClick = buttonClick;
|
|
555
|
-
this._s.namespace = 'dtcc-' + _namespace++;
|
|
556
|
-
this._dom.button.addEventListener('click', buttonClick);
|
|
557
|
-
this._dom.button.addEventListener('keypress', buttonClick);
|
|
558
|
-
this._s.host.destroyAdd(this);
|
|
559
|
-
return this;
|
|
560
|
-
};
|
|
561
|
-
/**
|
|
562
|
-
* Set the icon to display in the button
|
|
563
|
-
*
|
|
564
|
-
* @param icon Icon name
|
|
565
|
-
* @returns Button instance
|
|
566
|
-
*/
|
|
567
|
-
Button.prototype.icon = function (icon) {
|
|
568
|
-
this._dom.icon.innerHTML = icon ? icons[icon] : '';
|
|
569
|
-
return this;
|
|
570
|
-
};
|
|
571
|
-
Button.prototype.text = function (text) {
|
|
572
|
-
if (text === undefined) {
|
|
573
|
-
return this._s.label;
|
|
574
|
-
}
|
|
575
|
-
this._dom.text.innerHTML = text;
|
|
576
|
-
this._s.label = text; // for fast retrieval
|
|
577
|
-
this._dom.button.setAttribute('aria-label', text);
|
|
578
|
-
return this;
|
|
579
|
-
};
|
|
580
|
-
Button.prototype.value = function (val) {
|
|
581
|
-
if (val === undefined) {
|
|
582
|
-
return this._s.value;
|
|
583
|
-
}
|
|
584
|
-
this._s.value = val;
|
|
585
|
-
return this;
|
|
586
|
-
};
|
|
587
|
-
/**
|
|
588
|
-
* Check if anything is making this button active
|
|
589
|
-
*
|
|
590
|
-
* @returns Self for chaining
|
|
591
|
-
*/
|
|
592
|
-
Button.prototype._checkActive = function () {
|
|
593
|
-
if (this._s.active === true || Object.values(this._s.activeList).includes(true)) {
|
|
594
|
-
this._dom.state.innerHTML = icons.tick;
|
|
595
|
-
this._dom.button.classList.add('dtcc-button_active');
|
|
596
|
-
}
|
|
597
|
-
else {
|
|
598
|
-
this._dom.state.innerHTML = '';
|
|
599
|
-
this._dom.button.classList.remove('dtcc-button_active');
|
|
600
|
-
}
|
|
601
|
-
return this;
|
|
602
|
-
};
|
|
603
|
-
Button.classes = {
|
|
604
|
-
container: 'dtcc-button'
|
|
605
|
-
};
|
|
606
|
-
return Button;
|
|
607
|
-
}());
|
|
608
|
-
|
|
609
|
-
var CheckList = /** @class */ (function () {
|
|
610
|
-
/**
|
|
611
|
-
* Container for a list of buttons
|
|
612
|
-
*/
|
|
613
|
-
function CheckList(dt, host, opts) {
|
|
614
|
-
var _this = this;
|
|
615
|
-
this._s = {
|
|
616
|
-
buttons: [],
|
|
617
|
-
dt: null,
|
|
618
|
-
handler: function () { },
|
|
619
|
-
host: null,
|
|
620
|
-
search: ''
|
|
621
|
-
};
|
|
622
|
-
this._s.dt = dt;
|
|
623
|
-
this._s.host = host;
|
|
624
|
-
this._dom = {
|
|
625
|
-
buttons: createElement('div', 'dtcc-list-buttons'),
|
|
626
|
-
container: createElement('div', CheckList.classes.container),
|
|
627
|
-
controls: createElement('div', 'dtcc-list-controls'),
|
|
628
|
-
empty: createElement('div', 'dtcc-list-empty', dt.i18n('columnControl.list.empty', 'No options')),
|
|
629
|
-
title: createElement('div', 'dtcc-list-title'),
|
|
630
|
-
selectAll: createElement('button', 'dtcc-list-selectAll', dt.i18n('columnControl.list.all', 'Select all')),
|
|
631
|
-
selectAllCount: createElement('span'),
|
|
632
|
-
selectNone: createElement('button', 'dtcc-list-selectNone', dt.i18n('columnControl.list.none', 'Deselect')),
|
|
633
|
-
selectNoneCount: createElement('span'),
|
|
634
|
-
search: createElement('input', CheckList.classes.input)
|
|
635
|
-
};
|
|
636
|
-
var dom = this._dom;
|
|
637
|
-
dom.search.setAttribute('type', 'text');
|
|
638
|
-
dom.container.append(dom.title);
|
|
639
|
-
dom.container.append(dom.controls);
|
|
640
|
-
dom.container.append(dom.empty);
|
|
641
|
-
dom.container.append(dom.buttons);
|
|
642
|
-
if (opts.select) {
|
|
643
|
-
dom.controls.append(dom.selectAll);
|
|
644
|
-
dom.controls.append(dom.selectNone);
|
|
645
|
-
dom.selectAll.append(dom.selectAllCount);
|
|
646
|
-
dom.selectNone.append(dom.selectNoneCount);
|
|
647
|
-
dom.selectAll.setAttribute('type', 'button');
|
|
648
|
-
dom.selectNone.setAttribute('type', 'button');
|
|
649
|
-
}
|
|
650
|
-
// Events
|
|
651
|
-
var searchInput = function () {
|
|
652
|
-
_this._s.search = dom.search.value;
|
|
653
|
-
_this._redraw();
|
|
654
|
-
};
|
|
655
|
-
var selectAllClick = function (e) {
|
|
656
|
-
_this.selectAll();
|
|
657
|
-
_this._s.handler(e, null, _this._s.buttons, true);
|
|
658
|
-
_this._updateCount();
|
|
659
|
-
};
|
|
660
|
-
var selectNoneClick = function (e) {
|
|
661
|
-
_this.selectNone();
|
|
662
|
-
_this._s.handler(e, null, _this._s.buttons, true);
|
|
663
|
-
_this._updateCount();
|
|
664
|
-
};
|
|
665
|
-
if (opts.search) {
|
|
666
|
-
dom.controls.append(dom.search);
|
|
667
|
-
dom.search.setAttribute('placeholder', dt.i18n('columnControl.list.search', 'Search...'));
|
|
668
|
-
dom.search.addEventListener('input', searchInput);
|
|
669
|
-
}
|
|
670
|
-
dom.selectAll.addEventListener('click', selectAllClick);
|
|
671
|
-
dom.selectNone.addEventListener('click', selectNoneClick);
|
|
672
|
-
dt.on('destroy', function () {
|
|
673
|
-
dom.selectAll.removeEventListener('click', selectAllClick);
|
|
674
|
-
dom.selectNone.removeEventListener('click', selectNoneClick);
|
|
675
|
-
dom.search.removeEventListener('input', searchInput);
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* Add one or more buttons to the list
|
|
680
|
-
*
|
|
681
|
-
* @param options Configuration for the button(s) to add
|
|
682
|
-
* @returns Self for chaining
|
|
683
|
-
*/
|
|
684
|
-
CheckList.prototype.add = function (options, update) {
|
|
685
|
-
var _this = this;
|
|
686
|
-
if (!Array.isArray(options)) {
|
|
687
|
-
options = [options];
|
|
688
|
-
}
|
|
689
|
-
var _loop_1 = function (i) {
|
|
690
|
-
var option = options[i];
|
|
691
|
-
var btn = new Button(this_1._s.dt, this_1._s.host)
|
|
692
|
-
.active(option.active || false)
|
|
693
|
-
.handler(function (e) {
|
|
694
|
-
_this._s.handler(e, btn, _this._s.buttons, true);
|
|
695
|
-
_this._updateCount();
|
|
696
|
-
})
|
|
697
|
-
.icon(option.icon || '')
|
|
698
|
-
.text(option.label !== ''
|
|
699
|
-
? option.label
|
|
700
|
-
: this_1._s.dt.i18n('columnControl.list.empty', 'Empty'))
|
|
701
|
-
.value(option.value);
|
|
702
|
-
if (option.label === '') {
|
|
703
|
-
btn.className('empty');
|
|
704
|
-
}
|
|
705
|
-
this_1._s.buttons.push(btn);
|
|
706
|
-
};
|
|
707
|
-
var this_1 = this;
|
|
708
|
-
for (var i = 0; i < options.length; i++) {
|
|
709
|
-
_loop_1(i);
|
|
710
|
-
}
|
|
711
|
-
var count = this._s.buttons.length;
|
|
712
|
-
if (update === true || update === undefined) {
|
|
713
|
-
this._dom.selectAllCount.innerHTML = count ? '(' + count + ')' : '';
|
|
714
|
-
this._redraw();
|
|
715
|
-
}
|
|
716
|
-
return this;
|
|
717
|
-
};
|
|
718
|
-
/**
|
|
719
|
-
* Find a button with a given value
|
|
720
|
-
*
|
|
721
|
-
* @param val Value to search for
|
|
722
|
-
* @returns Found button
|
|
723
|
-
*/
|
|
724
|
-
CheckList.prototype.button = function (val) {
|
|
725
|
-
var buttons = this._s.buttons;
|
|
726
|
-
for (var i = 0; i < buttons.length; i++) {
|
|
727
|
-
if (buttons[i].value() === val) {
|
|
728
|
-
return buttons[i];
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
return null;
|
|
732
|
-
};
|
|
733
|
-
/**
|
|
734
|
-
* Remove all buttons from the list
|
|
735
|
-
*
|
|
736
|
-
* @returns Self for chaining
|
|
737
|
-
*/
|
|
738
|
-
CheckList.prototype.clear = function () {
|
|
739
|
-
// Clean up the buttons
|
|
740
|
-
for (var i = 0; i < this._s.buttons.length; i++) {
|
|
741
|
-
this._s.buttons[i].destroy();
|
|
742
|
-
}
|
|
743
|
-
// Then empty them out
|
|
744
|
-
this._dom.buttons.replaceChildren();
|
|
745
|
-
this._s.buttons.length = 0;
|
|
746
|
-
return this;
|
|
747
|
-
};
|
|
748
|
-
/**
|
|
749
|
-
* Get the DOM container element to attach into the document
|
|
750
|
-
*
|
|
751
|
-
* @returns Container
|
|
752
|
-
*/
|
|
753
|
-
CheckList.prototype.element = function () {
|
|
754
|
-
return this._dom.container;
|
|
755
|
-
};
|
|
756
|
-
/**
|
|
757
|
-
* Set the event handler for what happens when a button is clicked
|
|
758
|
-
*
|
|
759
|
-
* @param fn Event handler
|
|
760
|
-
*/
|
|
761
|
-
CheckList.prototype.handler = function (fn) {
|
|
762
|
-
this._s.handler = fn;
|
|
763
|
-
return this;
|
|
764
|
-
};
|
|
765
|
-
/**
|
|
766
|
-
* Indicate that this is a search control and should listen for corresponding events
|
|
767
|
-
*
|
|
768
|
-
* @param dt DataTable instance
|
|
769
|
-
* @param idx Column index
|
|
770
|
-
*/
|
|
771
|
-
CheckList.prototype.searchListener = function (dt) {
|
|
772
|
-
var _this = this;
|
|
773
|
-
// Column control search clearing (column().columnControl.searchClear() method)
|
|
774
|
-
dt.on('cc-search-clear', function (e, colIdx) {
|
|
775
|
-
if (colIdx === _this._s.host.idx()) {
|
|
776
|
-
_this.selectNone();
|
|
777
|
-
_this._s.handler(e, null, _this._s.buttons, false);
|
|
778
|
-
_this._s.search = '';
|
|
779
|
-
_this._dom.search.value = '';
|
|
780
|
-
_this._redraw();
|
|
781
|
-
_this._updateCount();
|
|
782
|
-
}
|
|
783
|
-
});
|
|
784
|
-
return this;
|
|
785
|
-
};
|
|
786
|
-
/**
|
|
787
|
-
* Select all buttons
|
|
788
|
-
*
|
|
789
|
-
* @returns Self for chaining
|
|
790
|
-
*/
|
|
791
|
-
CheckList.prototype.selectAll = function () {
|
|
792
|
-
for (var i = 0; i < this._s.buttons.length; i++) {
|
|
793
|
-
this._s.buttons[i].active(true);
|
|
794
|
-
}
|
|
795
|
-
return this;
|
|
796
|
-
};
|
|
797
|
-
/**
|
|
798
|
-
* Deselect all buttons
|
|
799
|
-
*
|
|
800
|
-
* @returns Self for chaining
|
|
801
|
-
*/
|
|
802
|
-
CheckList.prototype.selectNone = function () {
|
|
803
|
-
for (var i = 0; i < this._s.buttons.length; i++) {
|
|
804
|
-
this._s.buttons[i].active(false);
|
|
805
|
-
}
|
|
806
|
-
return this;
|
|
807
|
-
};
|
|
808
|
-
/**
|
|
809
|
-
* Set the list's title
|
|
810
|
-
*
|
|
811
|
-
* @param title Display title
|
|
812
|
-
* @returns Button instance
|
|
813
|
-
*/
|
|
814
|
-
CheckList.prototype.title = function (title) {
|
|
815
|
-
this._dom.title.innerHTML = title;
|
|
816
|
-
return this;
|
|
817
|
-
};
|
|
818
|
-
CheckList.prototype.values = function (values) {
|
|
819
|
-
var i;
|
|
820
|
-
var result = [];
|
|
821
|
-
var buttons = this._s.buttons;
|
|
822
|
-
if (values !== undefined) {
|
|
823
|
-
for (i = 0; i < buttons.length; i++) {
|
|
824
|
-
if (values.includes(buttons[i].value())) {
|
|
825
|
-
buttons[i].active(true);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
this._updateCount();
|
|
829
|
-
return this;
|
|
830
|
-
}
|
|
831
|
-
for (i = 0; i < buttons.length; i++) {
|
|
832
|
-
if (buttons[i].active()) {
|
|
833
|
-
result.push(buttons[i].value());
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
return result;
|
|
837
|
-
};
|
|
838
|
-
/**
|
|
839
|
-
* Update the deselect counter
|
|
840
|
-
*/
|
|
841
|
-
CheckList.prototype._updateCount = function () {
|
|
842
|
-
var count = this.values().length;
|
|
843
|
-
this._dom.selectNoneCount.innerHTML = count ? '(' + count + ')' : '';
|
|
844
|
-
};
|
|
845
|
-
/**
|
|
846
|
-
* Add the buttons to the page - taking into account filtering
|
|
847
|
-
*/
|
|
848
|
-
CheckList.prototype._redraw = function () {
|
|
849
|
-
var buttons = this._s.buttons;
|
|
850
|
-
var el = this._dom.buttons;
|
|
851
|
-
var searchTerm = this._s.search.toLowerCase();
|
|
852
|
-
el.replaceChildren();
|
|
853
|
-
for (var i = 0; i < buttons.length; i++) {
|
|
854
|
-
var btn = buttons[i];
|
|
855
|
-
if (!searchTerm ||
|
|
856
|
-
btn
|
|
857
|
-
.text()
|
|
858
|
-
.toLowerCase()
|
|
859
|
-
.includes(searchTerm)) {
|
|
860
|
-
el.appendChild(btn.element());
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
this._dom.empty.style.display = buttons.length === 0 ? 'block' : 'none';
|
|
864
|
-
el.style.display = buttons.length > 0 ? 'block' : 'none';
|
|
865
|
-
};
|
|
866
|
-
CheckList.classes = {
|
|
867
|
-
container: 'dtcc-list',
|
|
868
|
-
input: 'dtcc-list-search'
|
|
869
|
-
};
|
|
870
|
-
return CheckList;
|
|
871
|
-
}());
|
|
872
|
-
|
|
873
|
-
var colVis = {
|
|
874
|
-
defaults: {
|
|
875
|
-
className: 'colVis',
|
|
876
|
-
columns: '',
|
|
877
|
-
search: false,
|
|
878
|
-
select: false,
|
|
879
|
-
title: 'Column visibility'
|
|
880
|
-
},
|
|
881
|
-
init: function (config) {
|
|
882
|
-
var dt = this.dt();
|
|
883
|
-
var checkList = new CheckList(dt, this, {
|
|
884
|
-
search: config.search,
|
|
885
|
-
select: config.select
|
|
886
|
-
})
|
|
887
|
-
.title(dt.i18n('columnControl.colVis', config.title))
|
|
888
|
-
.handler(function (e, btn, buttons) {
|
|
889
|
-
if (btn) {
|
|
890
|
-
btn.active(!btn.active());
|
|
891
|
-
}
|
|
892
|
-
apply(buttons);
|
|
893
|
-
});
|
|
894
|
-
// Need to apply in a loop to allow for select all / select none
|
|
895
|
-
var apply = function (buttons) {
|
|
896
|
-
for (var i = 0; i < buttons.length; i++) {
|
|
897
|
-
var btn = buttons[i];
|
|
898
|
-
var idx = btn.value();
|
|
899
|
-
var col = dt.column(idx);
|
|
900
|
-
if (btn.active() && !col.visible()) {
|
|
901
|
-
col.visible(true);
|
|
902
|
-
}
|
|
903
|
-
else if (!btn.active() && col.visible()) {
|
|
904
|
-
col.visible(false);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
var rebuild = function () {
|
|
909
|
-
var columns = dt.columns(config.columns);
|
|
910
|
-
columns.every(function () {
|
|
911
|
-
checkList.add({
|
|
912
|
-
active: this.visible(),
|
|
913
|
-
label: this.title(),
|
|
914
|
-
value: this.index()
|
|
915
|
-
});
|
|
916
|
-
});
|
|
917
|
-
};
|
|
918
|
-
rebuild();
|
|
919
|
-
dt.on('column-visibility', function (e, s, colIdx, state) {
|
|
920
|
-
var btn = checkList.button(colIdx);
|
|
921
|
-
if (btn) {
|
|
922
|
-
btn.active(state);
|
|
923
|
-
}
|
|
924
|
-
});
|
|
925
|
-
dt.on('columns-reordered', function (e, details) {
|
|
926
|
-
checkList.clear();
|
|
927
|
-
rebuild();
|
|
928
|
-
});
|
|
929
|
-
return checkList.element();
|
|
930
|
-
}
|
|
931
|
-
};
|
|
932
|
-
|
|
933
|
-
var colVisDropdown = {
|
|
934
|
-
defaults: {
|
|
935
|
-
className: 'colVis',
|
|
936
|
-
columns: '',
|
|
937
|
-
search: false,
|
|
938
|
-
select: false,
|
|
939
|
-
text: 'Column visibility',
|
|
940
|
-
title: 'Column visibility'
|
|
941
|
-
},
|
|
942
|
-
extend: function (config) {
|
|
943
|
-
var dt = this.dt();
|
|
944
|
-
return {
|
|
945
|
-
extend: 'dropdown',
|
|
946
|
-
icon: 'columns',
|
|
947
|
-
text: dt.i18n('columnControl.colVisDropdown', config.text),
|
|
948
|
-
content: [
|
|
949
|
-
Object.assign(config, {
|
|
950
|
-
extend: 'colVis'
|
|
951
|
-
})
|
|
952
|
-
]
|
|
953
|
-
};
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
|
|
957
|
-
var reorder = {
|
|
958
|
-
defaults: {
|
|
959
|
-
className: 'reorder',
|
|
960
|
-
icon: 'move',
|
|
961
|
-
text: 'Reorder columns'
|
|
962
|
-
},
|
|
963
|
-
init: function (config) {
|
|
964
|
-
var _this = this;
|
|
965
|
-
var dt = this.dt();
|
|
966
|
-
var btn = new Button(dt, this)
|
|
967
|
-
.text(dt.i18n('columnControl.reorder', config.text))
|
|
968
|
-
.icon(config.icon)
|
|
969
|
-
.className(config.className);
|
|
970
|
-
// The event handling for this is done in ColReorder._addListener - no event
|
|
971
|
-
// handler needed here for click / drag
|
|
972
|
-
if (this.idx() === 0) {
|
|
973
|
-
btn.enable(false);
|
|
974
|
-
}
|
|
975
|
-
dt.on('columns-reordered', function (e, details) {
|
|
976
|
-
btn.enable(_this.idx() > 0);
|
|
977
|
-
});
|
|
978
|
-
// If ColReorder wasn't initialised on this DataTable, then we need to add it
|
|
979
|
-
if (!dt.init().colReorder) {
|
|
980
|
-
new DataTable.ColReorder(dt, {});
|
|
981
|
-
}
|
|
982
|
-
return btn.element();
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
|
|
986
|
-
var reorderLeft = {
|
|
987
|
-
defaults: {
|
|
988
|
-
className: 'reorderLeft',
|
|
989
|
-
icon: 'moveLeft',
|
|
990
|
-
text: 'Move column left'
|
|
991
|
-
},
|
|
992
|
-
init: function (config) {
|
|
993
|
-
var _this = this;
|
|
994
|
-
var dt = this.dt();
|
|
995
|
-
var btn = new Button(dt, this)
|
|
996
|
-
.text(dt.i18n('columnControl.reorderLeft', config.text))
|
|
997
|
-
.icon(config.icon)
|
|
998
|
-
.className(config.className)
|
|
999
|
-
.handler(function () {
|
|
1000
|
-
var idx = _this.idx();
|
|
1001
|
-
// TODO account for visibility
|
|
1002
|
-
if (idx > 0) {
|
|
1003
|
-
dt.colReorder.move(idx, idx - 1);
|
|
1004
|
-
}
|
|
1005
|
-
});
|
|
1006
|
-
if (this.idx() === 0) {
|
|
1007
|
-
btn.enable(false);
|
|
1008
|
-
}
|
|
1009
|
-
dt.on('columns-reordered', function (e, details) {
|
|
1010
|
-
btn.enable(_this.idx() > 0);
|
|
1011
|
-
});
|
|
1012
|
-
return btn.element();
|
|
1013
|
-
}
|
|
1014
|
-
};
|
|
1015
|
-
|
|
1016
|
-
var reorderRight = {
|
|
1017
|
-
defaults: {
|
|
1018
|
-
className: 'reorderRight',
|
|
1019
|
-
icon: 'moveRight',
|
|
1020
|
-
text: 'Move column right'
|
|
1021
|
-
},
|
|
1022
|
-
init: function (config) {
|
|
1023
|
-
var _this = this;
|
|
1024
|
-
var dt = this.dt();
|
|
1025
|
-
var btn = new Button(dt, this)
|
|
1026
|
-
.text(dt.i18n('columnControl.reorderRight', config.text))
|
|
1027
|
-
.icon(config.icon)
|
|
1028
|
-
.className(config.className)
|
|
1029
|
-
.handler(function () {
|
|
1030
|
-
var idx = _this.idx();
|
|
1031
|
-
if (idx < dt.columns().count() - 1) {
|
|
1032
|
-
dt.colReorder.move(idx, idx + 1);
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1035
|
-
if (this.idx() === dt.columns().count() - 1) {
|
|
1036
|
-
btn.enable(false);
|
|
1037
|
-
}
|
|
1038
|
-
dt.on('columns-reordered', function (e, details) {
|
|
1039
|
-
btn.enable(_this.idx() < dt.columns().count() - 1);
|
|
1040
|
-
});
|
|
1041
|
-
return btn.element();
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1044
|
-
|
|
1045
|
-
var order = {
|
|
1046
|
-
defaults: {
|
|
1047
|
-
className: 'order',
|
|
1048
|
-
iconAsc: 'orderAsc',
|
|
1049
|
-
iconDesc: 'orderDesc',
|
|
1050
|
-
iconNone: 'orderNone',
|
|
1051
|
-
statusOnly: false,
|
|
1052
|
-
text: 'Toggle ordering'
|
|
1053
|
-
},
|
|
1054
|
-
init: function (config) {
|
|
1055
|
-
var _this = this;
|
|
1056
|
-
var dt = this.dt();
|
|
1057
|
-
var btn = new Button(dt, this)
|
|
1058
|
-
.text(dt.i18n('columnControl.order', config.text))
|
|
1059
|
-
.icon('orderAsc')
|
|
1060
|
-
.className(config.className);
|
|
1061
|
-
if (!config.statusOnly) {
|
|
1062
|
-
dt.order.listener(btn.element(), DataTable.versionCheck('2.3.2') ? function () { return [_this.idx()]; } : this.idx(), function () { });
|
|
1063
|
-
}
|
|
1064
|
-
dt.on('order', function (e, s, order) {
|
|
1065
|
-
var found = order.find(function (o) { return o.col === _this.idx(); });
|
|
1066
|
-
if (!found) {
|
|
1067
|
-
btn.active(false).icon(config.iconNone);
|
|
1068
|
-
}
|
|
1069
|
-
else if (found.dir === 'asc') {
|
|
1070
|
-
btn.active(true).icon(config.iconAsc);
|
|
1071
|
-
}
|
|
1072
|
-
else if (found.dir === 'desc') {
|
|
1073
|
-
btn.active(true).icon(config.iconDesc);
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
return btn.element();
|
|
1077
|
-
}
|
|
1078
|
-
};
|
|
1079
|
-
|
|
1080
|
-
var orderAddAsc = {
|
|
1081
|
-
defaults: {
|
|
1082
|
-
className: 'orderAddAsc',
|
|
1083
|
-
icon: 'orderAddAsc',
|
|
1084
|
-
text: 'Add Sort Ascending'
|
|
1085
|
-
},
|
|
1086
|
-
init: function (config) {
|
|
1087
|
-
var _this = this;
|
|
1088
|
-
var dt = this.dt();
|
|
1089
|
-
var btn = new Button(dt, this)
|
|
1090
|
-
.text(dt.i18n('columnControl.orderAddAsc', config.text))
|
|
1091
|
-
.icon(config.icon)
|
|
1092
|
-
.className(config.className)
|
|
1093
|
-
.handler(function () {
|
|
1094
|
-
var order = dt.order();
|
|
1095
|
-
order.push([_this.idx(), 'asc']);
|
|
1096
|
-
dt.draw();
|
|
1097
|
-
});
|
|
1098
|
-
dt.on('order', function (e, s, order) {
|
|
1099
|
-
var found = order.some(function (o) { return o.col === _this.idx(); });
|
|
1100
|
-
btn.enable(!found);
|
|
1101
|
-
});
|
|
1102
|
-
return btn.element();
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
1105
|
-
|
|
1106
|
-
var orderAddDesc = {
|
|
1107
|
-
defaults: {
|
|
1108
|
-
className: 'orderAddDesc',
|
|
1109
|
-
icon: 'orderAddDesc',
|
|
1110
|
-
text: 'Add Sort Descending'
|
|
1111
|
-
},
|
|
1112
|
-
init: function (config) {
|
|
1113
|
-
var _this = this;
|
|
1114
|
-
var dt = this.dt();
|
|
1115
|
-
var btn = new Button(dt, this)
|
|
1116
|
-
.text(dt.i18n('columnControl.orderAddDesc', config.text))
|
|
1117
|
-
.icon(config.icon)
|
|
1118
|
-
.className(config.className)
|
|
1119
|
-
.handler(function () {
|
|
1120
|
-
var order = dt.order();
|
|
1121
|
-
order.push([_this.idx(), 'desc']);
|
|
1122
|
-
dt.draw();
|
|
1123
|
-
});
|
|
1124
|
-
dt.on('order', function (e, s, order) {
|
|
1125
|
-
var found = order.some(function (o) { return o.col === _this.idx(); });
|
|
1126
|
-
btn.enable(!found);
|
|
1127
|
-
});
|
|
1128
|
-
return btn.element();
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
|
|
1132
|
-
var orderAsc = {
|
|
1133
|
-
defaults: {
|
|
1134
|
-
className: 'orderAsc',
|
|
1135
|
-
icon: 'orderAsc',
|
|
1136
|
-
text: 'Sort Ascending'
|
|
1137
|
-
},
|
|
1138
|
-
init: function (config) {
|
|
1139
|
-
var _this = this;
|
|
1140
|
-
var dt = this.dt();
|
|
1141
|
-
var btn = new Button(dt, this)
|
|
1142
|
-
.text(dt.i18n('columnControl.orderAsc', config.text))
|
|
1143
|
-
.icon(config.icon)
|
|
1144
|
-
.className(config.className)
|
|
1145
|
-
.handler(function () {
|
|
1146
|
-
_this.dt()
|
|
1147
|
-
.order([
|
|
1148
|
-
{
|
|
1149
|
-
idx: _this.idx(),
|
|
1150
|
-
dir: 'asc'
|
|
1151
|
-
}
|
|
1152
|
-
])
|
|
1153
|
-
.draw();
|
|
1154
|
-
});
|
|
1155
|
-
dt.on('order', function (e, s, order) {
|
|
1156
|
-
var found = order.some(function (o) { return o.col === _this.idx() && o.dir === 'asc'; });
|
|
1157
|
-
btn.active(found);
|
|
1158
|
-
});
|
|
1159
|
-
return btn.element();
|
|
1160
|
-
}
|
|
1161
|
-
};
|
|
1162
|
-
|
|
1163
|
-
var orderClear = {
|
|
1164
|
-
defaults: {
|
|
1165
|
-
className: 'orderClear',
|
|
1166
|
-
icon: 'orderClear',
|
|
1167
|
-
text: 'Clear sort'
|
|
1168
|
-
},
|
|
1169
|
-
init: function (config) {
|
|
1170
|
-
var dt = this.dt();
|
|
1171
|
-
var btn = new Button(dt, this)
|
|
1172
|
-
.text(dt.i18n('columnControl.orderClear', config.text))
|
|
1173
|
-
.icon(config.icon)
|
|
1174
|
-
.className(config.className)
|
|
1175
|
-
.handler(function () {
|
|
1176
|
-
dt.order([]).draw();
|
|
1177
|
-
});
|
|
1178
|
-
dt.on('order', function (e, s, order) {
|
|
1179
|
-
btn.enable(order.length > 0);
|
|
1180
|
-
});
|
|
1181
|
-
if (dt.order().length === 0) {
|
|
1182
|
-
btn.enable(false);
|
|
1183
|
-
}
|
|
1184
|
-
return btn.element();
|
|
1185
|
-
}
|
|
1186
|
-
};
|
|
1187
|
-
|
|
1188
|
-
var orderDesc = {
|
|
1189
|
-
defaults: {
|
|
1190
|
-
className: 'orderDesc',
|
|
1191
|
-
icon: 'orderDesc',
|
|
1192
|
-
text: 'Sort Descending'
|
|
1193
|
-
},
|
|
1194
|
-
init: function (config) {
|
|
1195
|
-
var _this = this;
|
|
1196
|
-
var dt = this.dt();
|
|
1197
|
-
var btn = new Button(dt, this)
|
|
1198
|
-
.text(dt.i18n('columnControl.orderDesc', config.text))
|
|
1199
|
-
.icon(config.icon)
|
|
1200
|
-
.className(config.className)
|
|
1201
|
-
.handler(function () {
|
|
1202
|
-
_this.dt()
|
|
1203
|
-
.order([
|
|
1204
|
-
{
|
|
1205
|
-
idx: _this.idx(),
|
|
1206
|
-
dir: 'desc'
|
|
1207
|
-
}
|
|
1208
|
-
])
|
|
1209
|
-
.draw();
|
|
1210
|
-
});
|
|
1211
|
-
dt.on('order', function (e, s, order) {
|
|
1212
|
-
var found = order.some(function (o) { return o.col === _this.idx() && o.dir === 'desc'; });
|
|
1213
|
-
btn.active(found);
|
|
1214
|
-
});
|
|
1215
|
-
return btn.element();
|
|
1216
|
-
}
|
|
1217
|
-
};
|
|
1218
|
-
|
|
1219
|
-
var orderRemove = {
|
|
1220
|
-
defaults: {
|
|
1221
|
-
className: 'orderRemove',
|
|
1222
|
-
icon: 'orderRemove',
|
|
1223
|
-
text: 'Remove from sort'
|
|
1224
|
-
},
|
|
1225
|
-
init: function (config) {
|
|
1226
|
-
var _this = this;
|
|
1227
|
-
var dt = this.dt();
|
|
1228
|
-
var btn = new Button(dt, this)
|
|
1229
|
-
.text(dt.i18n('columnControl.orderRemove', config.text))
|
|
1230
|
-
.icon(config.icon)
|
|
1231
|
-
.className(config.className)
|
|
1232
|
-
.handler(function () {
|
|
1233
|
-
// Remove the current column from the ordering array, then reorder the table
|
|
1234
|
-
var order = dt.order();
|
|
1235
|
-
var idx = order.findIndex(function (o) { return o[0] === _this.idx(); });
|
|
1236
|
-
order.splice(idx, 1);
|
|
1237
|
-
dt.order(order).draw();
|
|
1238
|
-
});
|
|
1239
|
-
dt.on('order', function (e, s, order) {
|
|
1240
|
-
var found = order.some(function (o) { return o.col === _this.idx(); });
|
|
1241
|
-
btn.enable(found);
|
|
1242
|
-
});
|
|
1243
|
-
btn.enable(false);
|
|
1244
|
-
return btn.element();
|
|
1245
|
-
}
|
|
1246
|
-
};
|
|
1247
|
-
|
|
1248
|
-
var orderStatus = {
|
|
1249
|
-
defaults: {
|
|
1250
|
-
className: 'order',
|
|
1251
|
-
iconAsc: 'orderAsc',
|
|
1252
|
-
iconDesc: 'orderDesc',
|
|
1253
|
-
iconNone: 'orderNone',
|
|
1254
|
-
statusOnly: true,
|
|
1255
|
-
text: 'Sort status'
|
|
1256
|
-
},
|
|
1257
|
-
extend: function (config) {
|
|
1258
|
-
return Object.assign(config, { extend: 'order' });
|
|
1259
|
-
}
|
|
1260
|
-
};
|
|
1261
|
-
|
|
1262
|
-
/**
|
|
1263
|
-
* Add an item to the grouping structure
|
|
1264
|
-
*
|
|
1265
|
-
* @param dt DataTable API instance
|
|
1266
|
-
* @param dataSrc Grouping data point to add
|
|
1267
|
-
* @returns Grouping array
|
|
1268
|
-
*/
|
|
1269
|
-
function rowGroupAdd$1(dt, dataSrc) {
|
|
1270
|
-
var applied = rowGroupApplied(dt);
|
|
1271
|
-
var idx = applied.indexOf(dataSrc);
|
|
1272
|
-
if (idx === -1) {
|
|
1273
|
-
applied.push(dataSrc);
|
|
1274
|
-
dt.rowGroup().dataSrc(applied);
|
|
1275
|
-
}
|
|
1276
|
-
return applied;
|
|
1277
|
-
}
|
|
1278
|
-
/**
|
|
1279
|
-
* Always want an array return
|
|
1280
|
-
*
|
|
1281
|
-
* @param dt DataTable API instance
|
|
1282
|
-
* @returns
|
|
1283
|
-
*/
|
|
1284
|
-
function rowGroupApplied(dt) {
|
|
1285
|
-
var applied = dt.rowGroup().dataSrc();
|
|
1286
|
-
return Array.isArray(applied)
|
|
1287
|
-
? applied
|
|
1288
|
-
: [applied];
|
|
1289
|
-
}
|
|
1290
|
-
/**
|
|
1291
|
-
* Remove all grouping
|
|
1292
|
-
*
|
|
1293
|
-
* @param dt DataTable API instance
|
|
1294
|
-
*/
|
|
1295
|
-
function rowGroupClear$1(dt) {
|
|
1296
|
-
dt.rowGroup().dataSrc([]);
|
|
1297
|
-
}
|
|
1298
|
-
/**
|
|
1299
|
-
* Remove an item from the grouping structure
|
|
1300
|
-
*
|
|
1301
|
-
* @param dt DataTable API instance
|
|
1302
|
-
* @param dataSrc Grouping data point to remove
|
|
1303
|
-
* @returns Grouping array
|
|
1304
|
-
*/
|
|
1305
|
-
function rowGroupRemove$1(dt, dataSrc) {
|
|
1306
|
-
var applied = rowGroupApplied(dt);
|
|
1307
|
-
var idx = applied.indexOf(dataSrc);
|
|
1308
|
-
if (idx !== -1) {
|
|
1309
|
-
applied.splice(idx, 1);
|
|
1310
|
-
dt.rowGroup().dataSrc(applied);
|
|
1311
|
-
}
|
|
1312
|
-
return applied;
|
|
1313
|
-
}
|
|
1314
|
-
var rowGroup = {
|
|
1315
|
-
defaults: {
|
|
1316
|
-
className: 'rowGroup',
|
|
1317
|
-
icon: 'groupTop',
|
|
1318
|
-
order: true,
|
|
1319
|
-
text: 'Group rows'
|
|
1320
|
-
},
|
|
1321
|
-
init: function (config) {
|
|
1322
|
-
var _this = this;
|
|
1323
|
-
var dt = this.dt();
|
|
1324
|
-
var btn = new Button(dt, this)
|
|
1325
|
-
.text(dt.i18n('columnControl.rowGroup', config.text))
|
|
1326
|
-
.icon(config.icon)
|
|
1327
|
-
.className(config.className)
|
|
1328
|
-
.handler(function () {
|
|
1329
|
-
var dataSrc = dt.column(_this.idx()).dataSrc();
|
|
1330
|
-
if (btn.active()) {
|
|
1331
|
-
// Grouping is active - remove
|
|
1332
|
-
rowGroupRemove$1(dt, dataSrc);
|
|
1333
|
-
}
|
|
1334
|
-
else {
|
|
1335
|
-
// No grouping by this column yet, set it
|
|
1336
|
-
rowGroupClear$1(dt);
|
|
1337
|
-
rowGroupAdd$1(dt, dataSrc);
|
|
1338
|
-
if (config.order !== false) {
|
|
1339
|
-
dt.order([_this.idx(), 'asc']);
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
dt.draw();
|
|
1343
|
-
});
|
|
1344
|
-
// Show as active when grouping is applied
|
|
1345
|
-
dt.on('rowgroup-datasrc', function () {
|
|
1346
|
-
var applied = rowGroupApplied(dt);
|
|
1347
|
-
var ours = dt.column(_this.idx()).dataSrc();
|
|
1348
|
-
btn.active(applied.includes(ours));
|
|
1349
|
-
});
|
|
1350
|
-
return btn.element();
|
|
1351
|
-
}
|
|
1352
|
-
};
|
|
1353
|
-
|
|
1354
|
-
var rowGroupAdd = {
|
|
1355
|
-
defaults: {
|
|
1356
|
-
className: 'rowGroupAdd',
|
|
1357
|
-
icon: 'groupAdd',
|
|
1358
|
-
order: true,
|
|
1359
|
-
text: 'Add to grouping'
|
|
1360
|
-
},
|
|
1361
|
-
init: function (config) {
|
|
1362
|
-
var _this = this;
|
|
1363
|
-
var dt = this.dt();
|
|
1364
|
-
var btn = new Button(dt, this)
|
|
1365
|
-
.text(dt.i18n('columnControl.rowGroup', config.text))
|
|
1366
|
-
.icon(config.icon)
|
|
1367
|
-
.className(config.className)
|
|
1368
|
-
.handler(function () {
|
|
1369
|
-
var dataSrc = dt.column(_this.idx()).dataSrc();
|
|
1370
|
-
if (btn.enable()) {
|
|
1371
|
-
// No grouping by this column yet, add it
|
|
1372
|
-
rowGroupAdd$1(dt, dataSrc);
|
|
1373
|
-
}
|
|
1374
|
-
dt.draw();
|
|
1375
|
-
});
|
|
1376
|
-
// Show as active when grouping is applied
|
|
1377
|
-
dt.on('rowgroup-datasrc', function () {
|
|
1378
|
-
var applied = rowGroupApplied(dt);
|
|
1379
|
-
var ours = dt.column(_this.idx()).dataSrc();
|
|
1380
|
-
btn.enable(!applied.includes(ours));
|
|
1381
|
-
});
|
|
1382
|
-
return btn.element();
|
|
1383
|
-
}
|
|
1384
|
-
};
|
|
1385
|
-
|
|
1386
|
-
var rowGroupClear = {
|
|
1387
|
-
defaults: {
|
|
1388
|
-
className: 'rowGroupClear',
|
|
1389
|
-
icon: 'groupClear',
|
|
1390
|
-
text: 'Clear all grouping'
|
|
1391
|
-
},
|
|
1392
|
-
init: function (config) {
|
|
1393
|
-
var dt = this.dt();
|
|
1394
|
-
var btn = new Button(dt, this)
|
|
1395
|
-
.text(dt.i18n('columnControl.rowGroup', config.text))
|
|
1396
|
-
.icon(config.icon)
|
|
1397
|
-
.className(config.className)
|
|
1398
|
-
.handler(function () {
|
|
1399
|
-
rowGroupClear$1(dt);
|
|
1400
|
-
dt.draw();
|
|
1401
|
-
});
|
|
1402
|
-
// Show as active when any grouping is applied
|
|
1403
|
-
dt.on('rowgroup-datasrc', function () {
|
|
1404
|
-
btn.enable(rowGroupApplied(dt).length > 0);
|
|
1405
|
-
});
|
|
1406
|
-
// Default status
|
|
1407
|
-
btn.enable(rowGroupApplied(dt).length > 0);
|
|
1408
|
-
return btn.element();
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
|
|
1412
|
-
var rowGroupRemove = {
|
|
1413
|
-
defaults: {
|
|
1414
|
-
className: 'rowGroupRemove',
|
|
1415
|
-
icon: 'groupRemove',
|
|
1416
|
-
order: true,
|
|
1417
|
-
text: 'Remove from grouping'
|
|
1418
|
-
},
|
|
1419
|
-
init: function (config) {
|
|
1420
|
-
var _this = this;
|
|
1421
|
-
var dt = this.dt();
|
|
1422
|
-
var btn = new Button(dt, this)
|
|
1423
|
-
.text(dt.i18n('columnControl.rowGroup', config.text))
|
|
1424
|
-
.icon(config.icon)
|
|
1425
|
-
.className(config.className)
|
|
1426
|
-
.handler(function () {
|
|
1427
|
-
var dataSrc = dt.column(_this.idx()).dataSrc();
|
|
1428
|
-
if (btn.enable()) {
|
|
1429
|
-
// Grouping is active - remove
|
|
1430
|
-
rowGroupRemove$1(dt, dataSrc);
|
|
1431
|
-
dt.draw();
|
|
1432
|
-
}
|
|
1433
|
-
});
|
|
1434
|
-
// Show as active when grouping is applied
|
|
1435
|
-
dt.on('rowgroup-datasrc', function () {
|
|
1436
|
-
var applied = rowGroupApplied(dt);
|
|
1437
|
-
var ours = dt.column(_this.idx()).dataSrc();
|
|
1438
|
-
btn.enable(applied.includes(ours));
|
|
1439
|
-
});
|
|
1440
|
-
// Default disabled
|
|
1441
|
-
btn.enable(false);
|
|
1442
|
-
return btn.element();
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1445
|
-
|
|
1446
|
-
var SearchInput = /** @class */ (function () {
|
|
1447
|
-
/**
|
|
1448
|
-
* Create a container element, for consistent DOM structure and styling
|
|
1449
|
-
*/
|
|
1450
|
-
function SearchInput(dt, idx) {
|
|
1451
|
-
var _this = this;
|
|
1452
|
-
this._type = 'text';
|
|
1453
|
-
this._sspTransform = null;
|
|
1454
|
-
this._sspData = {};
|
|
1455
|
-
this._dt = dt;
|
|
1456
|
-
this._idx = idx;
|
|
1457
|
-
this._dom = {
|
|
1458
|
-
clear: createElement('span', 'dtcc-search-clear', icons['x']),
|
|
1459
|
-
container: createElement('div', SearchInput.classes.container),
|
|
1460
|
-
typeIcon: createElement('div', 'dtcc-search-type-icon'),
|
|
1461
|
-
searchIcon: createElement('div', 'dtcc-search-icon', icons['search']),
|
|
1462
|
-
input: createElement('input', SearchInput.classes.input),
|
|
1463
|
-
inputs: createElement('div'),
|
|
1464
|
-
select: createElement('select', SearchInput.classes.select),
|
|
1465
|
-
title: createElement('div', 'dtcc-search-title')
|
|
1466
|
-
};
|
|
1467
|
-
var dom = this._dom;
|
|
1468
|
-
var originalIdx = idx;
|
|
1469
|
-
dom.input.setAttribute('type', 'text');
|
|
1470
|
-
dom.container.append(dom.title, dom.inputs);
|
|
1471
|
-
dom.inputs.append(dom.typeIcon, dom.select, dom.searchIcon, dom.clear, dom.input);
|
|
1472
|
-
// Listeners
|
|
1473
|
-
var inputInput = function () {
|
|
1474
|
-
_this.runSearch();
|
|
1475
|
-
};
|
|
1476
|
-
var selectInput = function () {
|
|
1477
|
-
dom.typeIcon.innerHTML = icons[dom.select.value];
|
|
1478
|
-
_this.runSearch();
|
|
1479
|
-
};
|
|
1480
|
-
var clearClick = function () {
|
|
1481
|
-
_this.clear();
|
|
1482
|
-
};
|
|
1483
|
-
dom.input.addEventListener('input', inputInput);
|
|
1484
|
-
dom.select.addEventListener('input', selectInput);
|
|
1485
|
-
dom.clear.addEventListener('click', clearClick);
|
|
1486
|
-
dt.on('destroy', function () {
|
|
1487
|
-
dom.input.removeEventListener('input', inputInput);
|
|
1488
|
-
dom.select.removeEventListener('input', selectInput);
|
|
1489
|
-
dom.clear.removeEventListener('click', clearClick);
|
|
1490
|
-
});
|
|
1491
|
-
// State handling - all components that use this class have the same state saving structure
|
|
1492
|
-
// so shared handling can be performed here.
|
|
1493
|
-
dt.on('stateSaveParams.DT', function (e, s, data) {
|
|
1494
|
-
if (!data.columnControl) {
|
|
1495
|
-
data.columnControl = {};
|
|
1496
|
-
}
|
|
1497
|
-
if (!data.columnControl[_this._idx]) {
|
|
1498
|
-
data.columnControl[_this._idx] = {};
|
|
1499
|
-
}
|
|
1500
|
-
data.columnControl[_this._idx].searchInput = {
|
|
1501
|
-
logic: dom.select.value,
|
|
1502
|
-
type: _this._type,
|
|
1503
|
-
value: dom.input.value
|
|
1504
|
-
};
|
|
1505
|
-
});
|
|
1506
|
-
dt.on('stateLoaded.DT', function (e, s, state) {
|
|
1507
|
-
_this._stateLoad(state);
|
|
1508
|
-
});
|
|
1509
|
-
// Same as for ColumnControl - reassign a column index if needed.
|
|
1510
|
-
dt.on('columns-reordered.DT', function (e, details) {
|
|
1511
|
-
_this._idx = dt.colReorder.transpose(originalIdx, 'fromOriginal');
|
|
1512
|
-
});
|
|
1513
|
-
// Column control search clearing (column().columnControl.searchClear() method)
|
|
1514
|
-
dt.on('cc-search-clear.DT', function (e, colIdx) {
|
|
1515
|
-
if (colIdx === _this._idx) {
|
|
1516
|
-
// Don't want an automatic redraw on this event
|
|
1517
|
-
_this._loadingState = true;
|
|
1518
|
-
_this.clear();
|
|
1519
|
-
_this._loadingState = false;
|
|
1520
|
-
}
|
|
1521
|
-
});
|
|
1522
|
-
// Data for server-side processing
|
|
1523
|
-
if (dt.page.info().serverSide) {
|
|
1524
|
-
dt.on('preXhr.DT', function (e, s, d) {
|
|
1525
|
-
// The column has been removed from the submit data - can't do anything
|
|
1526
|
-
if (!d.columns || !d.columns[_this._idx]) {
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
if (!d.columns[_this._idx].columnControl) {
|
|
1530
|
-
d.columns[_this._idx].columnControl = {};
|
|
1531
|
-
}
|
|
1532
|
-
var val = _this._dom.input.value;
|
|
1533
|
-
if (_this._sspTransform) {
|
|
1534
|
-
val = _this._sspTransform(val);
|
|
1535
|
-
}
|
|
1536
|
-
d.columns[_this._idx].columnControl.search = Object.assign({
|
|
1537
|
-
value: val,
|
|
1538
|
-
logic: _this._dom.select.value,
|
|
1539
|
-
type: _this._type
|
|
1540
|
-
}, _this._sspData);
|
|
1541
|
-
});
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
/**
|
|
1545
|
-
* Add a class to the container
|
|
1546
|
-
*
|
|
1547
|
-
* @param name Class name to add
|
|
1548
|
-
* @returns Self for chaining
|
|
1549
|
-
*/
|
|
1550
|
-
SearchInput.prototype.addClass = function (name) {
|
|
1551
|
-
this._dom.container.classList.add(name);
|
|
1552
|
-
return this;
|
|
1553
|
-
};
|
|
1554
|
-
/**
|
|
1555
|
-
* Clear any applied search
|
|
1556
|
-
*
|
|
1557
|
-
* @returns Self for chaining
|
|
1558
|
-
*/
|
|
1559
|
-
SearchInput.prototype.clear = function () {
|
|
1560
|
-
this.set(this._dom.select.children[0].getAttribute('value'), '');
|
|
1561
|
-
return this;
|
|
1562
|
-
};
|
|
1563
|
-
/**
|
|
1564
|
-
* Set the clear icon feature can be used or not
|
|
1565
|
-
*
|
|
1566
|
-
* @param set Flag
|
|
1567
|
-
* @returns Self for chaining
|
|
1568
|
-
*/
|
|
1569
|
-
SearchInput.prototype.clearable = function (set) {
|
|
1570
|
-
// Note there is no add here as it is added by default and never used after setup, so
|
|
1571
|
-
// no need.
|
|
1572
|
-
if (!set) {
|
|
1573
|
-
this._dom.clear.remove();
|
|
1574
|
-
}
|
|
1575
|
-
return this;
|
|
1576
|
-
};
|
|
1577
|
-
/**
|
|
1578
|
-
* Get the container element
|
|
1579
|
-
*
|
|
1580
|
-
* @returns The container element
|
|
1581
|
-
*/
|
|
1582
|
-
SearchInput.prototype.element = function () {
|
|
1583
|
-
return this._dom.container;
|
|
1584
|
-
};
|
|
1585
|
-
/**
|
|
1586
|
-
* Get the HTML input element for this control
|
|
1587
|
-
*
|
|
1588
|
-
* @returns HTML Input element
|
|
1589
|
-
*/
|
|
1590
|
-
SearchInput.prototype.input = function () {
|
|
1591
|
-
return this._dom.input;
|
|
1592
|
-
};
|
|
1593
|
-
/**
|
|
1594
|
-
* Set the list of options for the dropdown
|
|
1595
|
-
*
|
|
1596
|
-
* @param opts List of options
|
|
1597
|
-
* @returns Self for chaining
|
|
1598
|
-
*/
|
|
1599
|
-
SearchInput.prototype.options = function (opts) {
|
|
1600
|
-
var select = this._dom.select;
|
|
1601
|
-
for (var i = 0; i < opts.length; i++) {
|
|
1602
|
-
select.add(new Option(opts[i].label, opts[i].value));
|
|
1603
|
-
}
|
|
1604
|
-
// Initial icon
|
|
1605
|
-
this._dom.typeIcon.innerHTML = icons[opts[0].value];
|
|
1606
|
-
return this;
|
|
1607
|
-
};
|
|
1608
|
-
/**
|
|
1609
|
-
* Set the placeholder attribute for the input element
|
|
1610
|
-
*
|
|
1611
|
-
* @param placeholder Placeholder string
|
|
1612
|
-
* @returns Self for chaining
|
|
1613
|
-
*/
|
|
1614
|
-
SearchInput.prototype.placeholder = function (placeholder) {
|
|
1615
|
-
if (placeholder) {
|
|
1616
|
-
var columnTitle = this._dt.column(this._idx).title();
|
|
1617
|
-
this._dom.input.placeholder = placeholder.replace('[title]', columnTitle);
|
|
1618
|
-
}
|
|
1619
|
-
return this;
|
|
1620
|
-
};
|
|
1621
|
-
/**
|
|
1622
|
-
* Run the search method
|
|
1623
|
-
*/
|
|
1624
|
-
SearchInput.prototype.runSearch = function () {
|
|
1625
|
-
var dom = this._dom;
|
|
1626
|
-
var isActive = dom.select.value === 'empty' ||
|
|
1627
|
-
dom.select.value === 'notEmpty' ||
|
|
1628
|
-
dom.input.value !== '';
|
|
1629
|
-
dom.container.classList.toggle('dtcc-search_active', isActive);
|
|
1630
|
-
if (this._search &&
|
|
1631
|
-
(this._lastValue !== dom.input.value || this._lastType !== dom.select.value)) {
|
|
1632
|
-
this._search(dom.select.value, dom.input.value, this._loadingState);
|
|
1633
|
-
this._lastValue = dom.input.value;
|
|
1634
|
-
this._lastType = dom.select.value;
|
|
1635
|
-
}
|
|
1636
|
-
};
|
|
1637
|
-
/**
|
|
1638
|
-
* Set the function that will be run when a search operation is required. Note that this can
|
|
1639
|
-
* trigger the function to run if there is a saved state.
|
|
1640
|
-
*
|
|
1641
|
-
* @param fn Search callback
|
|
1642
|
-
* @returns Self for chaining
|
|
1643
|
-
*/
|
|
1644
|
-
SearchInput.prototype.search = function (fn) {
|
|
1645
|
-
this._search = fn;
|
|
1646
|
-
// If there is a saved state, load it now that set up is done.
|
|
1647
|
-
this._stateLoad(this._dt.state.loaded());
|
|
1648
|
-
return this;
|
|
1649
|
-
};
|
|
1650
|
-
/**
|
|
1651
|
-
* Set a value for the search input
|
|
1652
|
-
*
|
|
1653
|
-
* @param logic Logic type
|
|
1654
|
-
* @param val Value
|
|
1655
|
-
* @returns Self for chaining
|
|
1656
|
-
*/
|
|
1657
|
-
SearchInput.prototype.set = function (logic, val) {
|
|
1658
|
-
var dom = this._dom;
|
|
1659
|
-
dom.input.value = val;
|
|
1660
|
-
dom.select.value = logic;
|
|
1661
|
-
dom.typeIcon.innerHTML = icons[dom.select.value];
|
|
1662
|
-
this.runSearch();
|
|
1663
|
-
return this;
|
|
1664
|
-
};
|
|
1665
|
-
/**
|
|
1666
|
-
* Set a function to transform the input value before SSP data submission
|
|
1667
|
-
*
|
|
1668
|
-
* @param fn Transform function
|
|
1669
|
-
* @returns Self for chaining
|
|
1670
|
-
*/
|
|
1671
|
-
SearchInput.prototype.sspTransform = function (fn) {
|
|
1672
|
-
this._sspTransform = fn;
|
|
1673
|
-
return this;
|
|
1674
|
-
};
|
|
1675
|
-
/**
|
|
1676
|
-
* Set extra information to be send to the server for server-side processing
|
|
1677
|
-
*
|
|
1678
|
-
* @param data Data object
|
|
1679
|
-
* @returns Self for chaining
|
|
1680
|
-
*/
|
|
1681
|
-
SearchInput.prototype.sspData = function (data) {
|
|
1682
|
-
this._sspData = data;
|
|
1683
|
-
return this;
|
|
1684
|
-
};
|
|
1685
|
-
/**
|
|
1686
|
-
* Set the text that will be shown as the title for the control
|
|
1687
|
-
*
|
|
1688
|
-
* @param text Set the title text
|
|
1689
|
-
* @returns Self for chaining
|
|
1690
|
-
*/
|
|
1691
|
-
SearchInput.prototype.title = function (text) {
|
|
1692
|
-
if (text) {
|
|
1693
|
-
var columnTitle = this._dt.column(this._idx).title();
|
|
1694
|
-
this._dom.title.innerHTML = text.replace('[title]', columnTitle);
|
|
1695
|
-
}
|
|
1696
|
-
return this;
|
|
1697
|
-
};
|
|
1698
|
-
/**
|
|
1699
|
-
* Set the title attribute for the input element
|
|
1700
|
-
*
|
|
1701
|
-
* @param title Title attribute string
|
|
1702
|
-
* @returns Self for chaining
|
|
1703
|
-
*/
|
|
1704
|
-
SearchInput.prototype.titleAttr = function (title) {
|
|
1705
|
-
if (title) {
|
|
1706
|
-
var columnTitle = this._dt.column(this._idx).title();
|
|
1707
|
-
this._dom.input.title = title.replace('[title]', columnTitle);
|
|
1708
|
-
}
|
|
1709
|
-
return this;
|
|
1710
|
-
};
|
|
1711
|
-
SearchInput.prototype.type = function (t) {
|
|
1712
|
-
this._type = t;
|
|
1713
|
-
return this;
|
|
1714
|
-
};
|
|
1715
|
-
/**
|
|
1716
|
-
* Load a DataTables state
|
|
1717
|
-
*
|
|
1718
|
-
* @param state State object being loaded
|
|
1719
|
-
*/
|
|
1720
|
-
SearchInput.prototype._stateLoad = function (state) {
|
|
1721
|
-
var _a, _b;
|
|
1722
|
-
var dom = this._dom;
|
|
1723
|
-
var idx = this._idx;
|
|
1724
|
-
var loadedState = (_b = (_a = state === null || state === void 0 ? void 0 : state.columnControl) === null || _a === void 0 ? void 0 : _a[idx]) === null || _b === void 0 ? void 0 : _b.searchInput;
|
|
1725
|
-
if (loadedState) {
|
|
1726
|
-
// The search callback needs to know if we are loading an existing state or not
|
|
1727
|
-
// so it can determine if it needs to draw the table. If it was a user input, then
|
|
1728
|
-
// it redraws, if it was a state load, then there should be no redraw.
|
|
1729
|
-
this._loadingState = true;
|
|
1730
|
-
dom.select.value = loadedState.logic;
|
|
1731
|
-
dom.input.value = loadedState.value;
|
|
1732
|
-
dom.select.dispatchEvent(new Event('input'));
|
|
1733
|
-
this._loadingState = false;
|
|
1734
|
-
}
|
|
1735
|
-
};
|
|
1736
|
-
SearchInput.classes = {
|
|
1737
|
-
container: ['dtcc-content', 'dtcc-search'],
|
|
1738
|
-
input: '',
|
|
1739
|
-
select: ''
|
|
1740
|
-
};
|
|
1741
|
-
return SearchInput;
|
|
1742
|
-
}());
|
|
1743
|
-
|
|
1744
|
-
var searchDateTime = {
|
|
1745
|
-
defaults: {
|
|
1746
|
-
clear: true,
|
|
1747
|
-
format: '',
|
|
1748
|
-
mask: '',
|
|
1749
|
-
placeholder: '',
|
|
1750
|
-
title: '',
|
|
1751
|
-
titleAttr: ''
|
|
1752
|
-
},
|
|
1753
|
-
init: function (config) {
|
|
1754
|
-
var _this = this;
|
|
1755
|
-
var fromPicker = false;
|
|
1756
|
-
var moment = DataTable.use('moment');
|
|
1757
|
-
var luxon = DataTable.use('luxon');
|
|
1758
|
-
var dt = this.dt();
|
|
1759
|
-
var i18nBase = 'columnControl.search.datetime.';
|
|
1760
|
-
var pickerFormat = '';
|
|
1761
|
-
var dataSrcFormat = '';
|
|
1762
|
-
var dateTime;
|
|
1763
|
-
var searchInput = new SearchInput(dt, this.idx())
|
|
1764
|
-
.type('date')
|
|
1765
|
-
.addClass('dtcc-searchDateTime')
|
|
1766
|
-
.sspTransform(function (val) { return toISO(val, pickerFormat, moment, luxon); })
|
|
1767
|
-
.sspData({ mask: config.mask })
|
|
1768
|
-
.clearable(config.clear)
|
|
1769
|
-
.placeholder(config.placeholder)
|
|
1770
|
-
.title(config.title)
|
|
1771
|
-
.titleAttr(config.titleAttr)
|
|
1772
|
-
.options([
|
|
1773
|
-
{ label: dt.i18n(i18nBase + 'equal', 'Equals'), value: 'equal' },
|
|
1774
|
-
{ label: dt.i18n(i18nBase + 'notEqual', 'Does not equal'), value: 'notEqual' },
|
|
1775
|
-
{ label: dt.i18n(i18nBase + 'greater', 'After'), value: 'greater' },
|
|
1776
|
-
{ label: dt.i18n(i18nBase + 'less', 'Before'), value: 'less' },
|
|
1777
|
-
{ label: dt.i18n(i18nBase + 'empty', 'Empty'), value: 'empty' },
|
|
1778
|
-
{ label: dt.i18n(i18nBase + 'notEmpty', 'Not empty'), value: 'notEmpty' }
|
|
1779
|
-
])
|
|
1780
|
-
.search(function (searchType, searchTerm, loadingState) {
|
|
1781
|
-
// When SSP, don't apply a filter here, SearchInput will add to the submit data
|
|
1782
|
-
if (dt.page.info().serverSide) {
|
|
1783
|
-
if (!loadingState) {
|
|
1784
|
-
dt.draw();
|
|
1785
|
-
}
|
|
1786
|
-
return;
|
|
1787
|
-
}
|
|
1788
|
-
var mask = config.mask;
|
|
1789
|
-
var column = dt.column(_this.idx());
|
|
1790
|
-
var search = searchTerm === ''
|
|
1791
|
-
? ''
|
|
1792
|
-
: dateToNum(dateTime && fromPicker ? dateTime.val() : searchTerm.trim(), pickerFormat, moment, luxon, mask);
|
|
1793
|
-
if (searchType === 'empty') {
|
|
1794
|
-
column.search.fixed('dtcc', function (haystack) { return !haystack; });
|
|
1795
|
-
}
|
|
1796
|
-
else if (searchType === 'notEmpty') {
|
|
1797
|
-
column.search.fixed('dtcc', function (haystack) { return !!haystack; });
|
|
1798
|
-
}
|
|
1799
|
-
else if (column.search.fixed('dtcc') === '' && search === '') {
|
|
1800
|
-
// No change - don't do anything
|
|
1801
|
-
return;
|
|
1802
|
-
}
|
|
1803
|
-
else if (!search) {
|
|
1804
|
-
// Clear search
|
|
1805
|
-
column.search.fixed('dtcc', '');
|
|
1806
|
-
}
|
|
1807
|
-
else if (searchType === 'equal') {
|
|
1808
|
-
// Use a function for matching - weak typing
|
|
1809
|
-
// Note that the haystack in the search function is the rendered date - it
|
|
1810
|
-
// might need to be converted back to a date
|
|
1811
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
1812
|
-
return dateToNum(haystack, dataSrcFormat, moment, luxon, mask) == search;
|
|
1813
|
-
});
|
|
1814
|
-
}
|
|
1815
|
-
else if (searchType === 'notEqual') {
|
|
1816
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
1817
|
-
return dateToNum(haystack, dataSrcFormat, moment, luxon, mask) != search;
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
|
-
else if (searchType === 'greater') {
|
|
1821
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
1822
|
-
return dateToNum(haystack, dataSrcFormat, moment, luxon, mask) > search;
|
|
1823
|
-
});
|
|
1824
|
-
}
|
|
1825
|
-
else if (searchType === 'less') {
|
|
1826
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
1827
|
-
return dateToNum(haystack, dataSrcFormat, moment, luxon, mask) < search;
|
|
1828
|
-
});
|
|
1829
|
-
}
|
|
1830
|
-
// If in a dropdown, set the parent levels as active
|
|
1831
|
-
if (config._parents) {
|
|
1832
|
-
config._parents.forEach(function (btn) {
|
|
1833
|
-
return btn.activeList(_this.unique(), !!column.search.fixed('dtcc'));
|
|
1834
|
-
});
|
|
1835
|
-
}
|
|
1836
|
-
if (!loadingState) {
|
|
1837
|
-
column.draw();
|
|
1838
|
-
}
|
|
1839
|
-
});
|
|
1840
|
-
// Once data has been loaded we can run DateTime with the specified format
|
|
1841
|
-
dt.ready(function () {
|
|
1842
|
-
var DateTime = DataTable.use('datetime');
|
|
1843
|
-
dataSrcFormat = getFormat(dt, _this.idx());
|
|
1844
|
-
pickerFormat = config.format
|
|
1845
|
-
? config.format
|
|
1846
|
-
: dataSrcFormat;
|
|
1847
|
-
if (DateTime) {
|
|
1848
|
-
dateTime = new DateTime(searchInput.input(), {
|
|
1849
|
-
format: pickerFormat,
|
|
1850
|
-
i18n: dt.settings()[0].oLanguage.datetime, // could be undefined
|
|
1851
|
-
onChange: function () {
|
|
1852
|
-
fromPicker = true;
|
|
1853
|
-
searchInput.runSearch();
|
|
1854
|
-
fromPicker = false;
|
|
1855
|
-
}
|
|
1856
|
-
});
|
|
1857
|
-
}
|
|
1858
|
-
});
|
|
1859
|
-
return searchInput.element();
|
|
1860
|
-
}
|
|
1861
|
-
};
|
|
1862
|
-
/**
|
|
1863
|
-
* Determine the formatting string for the date time information in the colum
|
|
1864
|
-
*
|
|
1865
|
-
* @param dt DataTable instance
|
|
1866
|
-
* @param column Column index
|
|
1867
|
-
* @returns Date / time formatting string
|
|
1868
|
-
*/
|
|
1869
|
-
function getFormat(dt, column) {
|
|
1870
|
-
var type = dt.column(column).type();
|
|
1871
|
-
if (!type) {
|
|
1872
|
-
// Assume that it is ISO unless otherwise specified - that is all DataTables can do anyway
|
|
1873
|
-
return 'YYYY-MM-DD';
|
|
1874
|
-
}
|
|
1875
|
-
else if (type === 'datetime') {
|
|
1876
|
-
// If no format was specified in the DT type, a Javascript native toLocaleDateString
|
|
1877
|
-
// was used. Need to work out what that format is in Moment or Luxon. We need to pass
|
|
1878
|
-
// a known value though the renderer and work out the format
|
|
1879
|
-
var renderer = dt.settings()[0].aoColumns[column].mRender;
|
|
1880
|
-
var resultPm = renderer('1999-08-07T23:05:04Z', 'display');
|
|
1881
|
-
var resultAm = renderer('1999-08-07T03:05:04Z', 'display');
|
|
1882
|
-
var leadingZero = resultAm.includes('03');
|
|
1883
|
-
// What formatter are we using?
|
|
1884
|
-
if (DataTable.use('moment')) {
|
|
1885
|
-
return resultPm
|
|
1886
|
-
.replace('23', leadingZero ? 'HH' : 'H')
|
|
1887
|
-
.replace('11', leadingZero ? 'hh' : 'h')
|
|
1888
|
-
.replace('05', 'mm')
|
|
1889
|
-
.replace('04', 'ss')
|
|
1890
|
-
.replace('PM', 'A')
|
|
1891
|
-
.replace('pm', 'a')
|
|
1892
|
-
.replace('07', 'DD')
|
|
1893
|
-
.replace('7', 'D')
|
|
1894
|
-
.replace('08', 'MM')
|
|
1895
|
-
.replace('8', 'M')
|
|
1896
|
-
.replace('1999', 'YYYY')
|
|
1897
|
-
.replace('99', 'YY');
|
|
1898
|
-
}
|
|
1899
|
-
else if (DataTable.use('luxon')) {
|
|
1900
|
-
return resultPm
|
|
1901
|
-
.replace('23', leadingZero ? 'HH' : 'H')
|
|
1902
|
-
.replace('11', leadingZero ? 'hh' : 'h')
|
|
1903
|
-
.replace('05', 'mm')
|
|
1904
|
-
.replace('04', 'ss')
|
|
1905
|
-
.replace('PM', 'a')
|
|
1906
|
-
.replace('07', 'dd')
|
|
1907
|
-
.replace('7', 'd')
|
|
1908
|
-
.replace('08', 'MM')
|
|
1909
|
-
.replace('8', 'M')
|
|
1910
|
-
.replace('1999', 'yyyy')
|
|
1911
|
-
.replace('99', 'yy');
|
|
1912
|
-
}
|
|
1913
|
-
else if (resultPm.includes('23') && resultPm.includes('1999')) {
|
|
1914
|
-
return 'YYYY-MM-DD hh:mm:ss';
|
|
1915
|
-
}
|
|
1916
|
-
else if (resultPm.includes('23')) {
|
|
1917
|
-
return 'hh:mm:ss';
|
|
1918
|
-
}
|
|
1919
|
-
// fall through to final return
|
|
1920
|
-
}
|
|
1921
|
-
else if (type.includes('datetime-')) {
|
|
1922
|
-
// Column was specified with a particular display format - we can extract that format from
|
|
1923
|
-
// the type, as it is part of the type name.
|
|
1924
|
-
return type.replace(/datetime-/g, '');
|
|
1925
|
-
}
|
|
1926
|
-
else if (type.includes('moment')) {
|
|
1927
|
-
return type.replace(/moment-/g, '');
|
|
1928
|
-
}
|
|
1929
|
-
else if (type.includes('luxon')) {
|
|
1930
|
-
return type.replace(/luxon-/g, '');
|
|
1931
|
-
}
|
|
1932
|
-
return 'YYYY-MM-DD';
|
|
1933
|
-
}
|
|
1934
|
-
/**
|
|
1935
|
-
* Convert from a source date / time value (usually a string) to a timestamp for comparisons.
|
|
1936
|
-
*
|
|
1937
|
-
* @param input Input value
|
|
1938
|
-
* @param srcFormat String format of the input
|
|
1939
|
-
* @param moment Moment instance, if it is available
|
|
1940
|
-
* @param luxon Luxon object, if it is available
|
|
1941
|
-
* @returns Time stamp - milliseconds
|
|
1942
|
-
*/
|
|
1943
|
-
function dateToNum(input, srcFormat, moment, luxon, mask) {
|
|
1944
|
-
var d;
|
|
1945
|
-
if (input === '') {
|
|
1946
|
-
return '';
|
|
1947
|
-
}
|
|
1948
|
-
if (input instanceof Date) {
|
|
1949
|
-
d = input;
|
|
1950
|
-
}
|
|
1951
|
-
else if (srcFormat !== 'YYYY-MM-DD' && (moment || luxon)) {
|
|
1952
|
-
d = new Date(moment
|
|
1953
|
-
? moment(input, srcFormat).unix() * 1000
|
|
1954
|
-
: luxon.DateTime.fromFormat(input, srcFormat).toMillis());
|
|
1955
|
-
}
|
|
1956
|
-
else {
|
|
1957
|
-
// new Date() with `/` separators will treat the input as local time, but with `-` it will
|
|
1958
|
-
// treat it as UTC. We want UTC so do a replacement
|
|
1959
|
-
d = new Date(input.replace(/\//g, '-'));
|
|
1960
|
-
}
|
|
1961
|
-
if (mask) {
|
|
1962
|
-
if (!mask.includes('YYYY')) {
|
|
1963
|
-
d.setFullYear(1970);
|
|
1964
|
-
}
|
|
1965
|
-
if (!mask.includes('MM')) {
|
|
1966
|
-
d.setUTCMonth(0);
|
|
1967
|
-
}
|
|
1968
|
-
if (!mask.includes('DD')) {
|
|
1969
|
-
d.setUTCDate(1);
|
|
1970
|
-
}
|
|
1971
|
-
if (!mask.includes('hh')) {
|
|
1972
|
-
d.setUTCHours(0);
|
|
1973
|
-
}
|
|
1974
|
-
if (!mask.includes('mm')) {
|
|
1975
|
-
d.setUTCMinutes(0);
|
|
1976
|
-
}
|
|
1977
|
-
if (!mask.includes('ss')) {
|
|
1978
|
-
// This will match milliseconds as well, but that's fine, you won't match mS but not S
|
|
1979
|
-
d.setUTCSeconds(0);
|
|
1980
|
-
}
|
|
1981
|
-
if (!mask.includes('sss')) {
|
|
1982
|
-
d.setUTCMilliseconds(0);
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
return d.getTime();
|
|
1986
|
-
}
|
|
1987
|
-
/**
|
|
1988
|
-
* Convert an input string to an ISO formatted date
|
|
1989
|
-
*
|
|
1990
|
-
* @param input Input value
|
|
1991
|
-
* @param srcFormat String format of the input
|
|
1992
|
-
* @param moment Moment instance, if it is available
|
|
1993
|
-
* @param luxon Luxon object, if it is available
|
|
1994
|
-
* @returns Value in ISO
|
|
1995
|
-
*/
|
|
1996
|
-
function toISO(input, srcFormat, moment, luxon) {
|
|
1997
|
-
if (input === '') {
|
|
1998
|
-
return '';
|
|
1999
|
-
}
|
|
2000
|
-
else if (srcFormat !== 'YYYY-MM-DD' && moment) {
|
|
2001
|
-
// TODO Does it have a time component?
|
|
2002
|
-
return moment.utc(input, srcFormat).toISOString();
|
|
2003
|
-
}
|
|
2004
|
-
else if (srcFormat !== 'YYYY-MM-DD' && luxon) {
|
|
2005
|
-
// TODO Does it have a time component?
|
|
2006
|
-
return luxon.DateTime.fromFormat(input, srcFormat).toISO();
|
|
2007
|
-
}
|
|
2008
|
-
// new Date() with `/` separators will treat the input as local time, but with `-` it will
|
|
2009
|
-
// treat it as UTC. We want UTC so do a replacement
|
|
2010
|
-
input = input.replace(/\//g, '-');
|
|
2011
|
-
return input;
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
/** Set the options to show in the list */
|
|
2015
|
-
function setOptions(checkList, opts) {
|
|
2016
|
-
var existing = checkList.values();
|
|
2017
|
-
checkList.clear();
|
|
2018
|
-
for (var i = 0; i < opts.length; i++) {
|
|
2019
|
-
if (typeof opts[i] === 'object') {
|
|
2020
|
-
checkList.add({
|
|
2021
|
-
active: false,
|
|
2022
|
-
label: opts[i].label,
|
|
2023
|
-
value: opts[i].value
|
|
2024
|
-
}, i === opts.length - 1);
|
|
2025
|
-
}
|
|
2026
|
-
else {
|
|
2027
|
-
checkList.add({
|
|
2028
|
-
active: false,
|
|
2029
|
-
label: opts[i],
|
|
2030
|
-
value: opts[i]
|
|
2031
|
-
}, i === opts.length - 1);
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
if (existing.length) {
|
|
2035
|
-
checkList.values(existing);
|
|
2036
|
-
}
|
|
2037
|
-
}
|
|
2038
|
-
/** Load a saved state */
|
|
2039
|
-
function getState(columnIdx, state) {
|
|
2040
|
-
var _a, _b;
|
|
2041
|
-
var loadedState = (_b = (_a = state === null || state === void 0 ? void 0 : state.columnControl) === null || _a === void 0 ? void 0 : _a[columnIdx]) === null || _b === void 0 ? void 0 : _b.searchList;
|
|
2042
|
-
if (loadedState) {
|
|
2043
|
-
return loadedState;
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
/** Get the options for a column from a DT JSON object */
|
|
2047
|
-
function getJsonOptions(dt, idx) {
|
|
2048
|
-
var _a;
|
|
2049
|
-
var json = (_a = dt.ajax.json()) === null || _a === void 0 ? void 0 : _a.columnControl;
|
|
2050
|
-
var column = dt.column(idx);
|
|
2051
|
-
var name = column.name();
|
|
2052
|
-
var dataSrc = column.dataSrc();
|
|
2053
|
-
if (json && json[name]) {
|
|
2054
|
-
// Found options matching the column's name - top priority
|
|
2055
|
-
return json[name];
|
|
2056
|
-
}
|
|
2057
|
-
else if (json && typeof dataSrc === 'string' && json[dataSrc]) {
|
|
2058
|
-
// Found options matching the column's data source string
|
|
2059
|
-
return json[dataSrc];
|
|
2060
|
-
}
|
|
2061
|
-
else if (json && json[idx]) {
|
|
2062
|
-
// Found options matching the column's data index
|
|
2063
|
-
return json[idx];
|
|
2064
|
-
}
|
|
2065
|
-
return null;
|
|
2066
|
-
}
|
|
2067
|
-
function reloadOptions(dt, config, idx, checkList, loadedValues) {
|
|
2068
|
-
var _a;
|
|
2069
|
-
// Was there options specified in the Ajax return?
|
|
2070
|
-
var json = (_a = dt.ajax.json()) === null || _a === void 0 ? void 0 : _a.columnControl;
|
|
2071
|
-
var options = [];
|
|
2072
|
-
var jsonOptions = getJsonOptions(dt, idx);
|
|
2073
|
-
if (jsonOptions) {
|
|
2074
|
-
options = jsonOptions;
|
|
2075
|
-
}
|
|
2076
|
-
else if (json && config.ajaxOnly) {
|
|
2077
|
-
if (config.hidable) {
|
|
2078
|
-
// Ajax only options - need to hide the search list
|
|
2079
|
-
checkList.element().style.display = 'none';
|
|
2080
|
-
// Check if the parent buttons should be hidden as well (they will be if there
|
|
2081
|
-
// is no visible content in them)
|
|
2082
|
-
if (config._parents) {
|
|
2083
|
-
config._parents.forEach(function (btn) { return btn.checkDisplay(); });
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
// No point in doing any further processing here
|
|
2087
|
-
return;
|
|
2088
|
-
}
|
|
2089
|
-
else if (!dt.page.info().serverSide) {
|
|
2090
|
-
// Either no ajax object (i.e. not an Ajax table), or no matching ajax options
|
|
2091
|
-
// for this column - get the values for the column, taking into account
|
|
2092
|
-
// orthogonal rendering
|
|
2093
|
-
var found = {};
|
|
2094
|
-
var rows = dt.rows({ order: idx }).indexes().toArray();
|
|
2095
|
-
var settings = dt.settings()[0];
|
|
2096
|
-
for (var i = 0; i < rows.length; i++) {
|
|
2097
|
-
var raw = settings.fastData(rows[i], idx, 'filter');
|
|
2098
|
-
var filter = raw !== null && raw !== undefined
|
|
2099
|
-
? raw.toString()
|
|
2100
|
-
: '';
|
|
2101
|
-
if (!found[filter]) {
|
|
2102
|
-
found[filter] = true;
|
|
2103
|
-
options.push({
|
|
2104
|
-
label: settings.fastData(rows[i], idx, config.orthogonal),
|
|
2105
|
-
value: filter
|
|
2106
|
-
});
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
setOptions(checkList, options);
|
|
2111
|
-
// If there was a state loaded at start up, then we need to set the visual
|
|
2112
|
-
// appearance to match
|
|
2113
|
-
if (loadedValues) {
|
|
2114
|
-
checkList.values(loadedValues);
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
var searchList = {
|
|
2118
|
-
defaults: {
|
|
2119
|
-
ajaxOnly: true,
|
|
2120
|
-
className: 'searchList',
|
|
2121
|
-
hidable: true,
|
|
2122
|
-
options: null,
|
|
2123
|
-
orthogonal: 'display',
|
|
2124
|
-
search: true,
|
|
2125
|
-
select: true,
|
|
2126
|
-
title: ''
|
|
2127
|
-
},
|
|
2128
|
-
init: function (config) {
|
|
2129
|
-
var _this = this;
|
|
2130
|
-
var loadedValues = null;
|
|
2131
|
-
var dt = this.dt();
|
|
2132
|
-
// The search can be applied from a stored start at start up before the options are
|
|
2133
|
-
// available. It can also be applied by user input, so it is generalised into this function.
|
|
2134
|
-
var applySearch = function (values) {
|
|
2135
|
-
// When SSP, don't do any client-side filtering
|
|
2136
|
-
if (dt.page.info().serverSide) {
|
|
2137
|
-
return;
|
|
2138
|
-
}
|
|
2139
|
-
var col = dt.column(_this.idx());
|
|
2140
|
-
if (!values) {
|
|
2141
|
-
return;
|
|
2142
|
-
}
|
|
2143
|
-
else if (values.length === 0) {
|
|
2144
|
-
// Nothing selected - clear the filter
|
|
2145
|
-
col.search.fixed('dtcc-list', '');
|
|
2146
|
-
}
|
|
2147
|
-
else {
|
|
2148
|
-
// Find all matching options from the list of values
|
|
2149
|
-
col.search.fixed('dtcc-list', function (val) {
|
|
2150
|
-
return values.includes(val);
|
|
2151
|
-
});
|
|
2152
|
-
}
|
|
2153
|
-
// If in a dropdown, set the parent levels as active
|
|
2154
|
-
if (config._parents) {
|
|
2155
|
-
config._parents.forEach(function (btn) { return btn.activeList(_this.unique(), !!values.length); });
|
|
2156
|
-
}
|
|
2157
|
-
};
|
|
2158
|
-
var checkList = new CheckList(dt, this, {
|
|
2159
|
-
search: config.search,
|
|
2160
|
-
select: config.select
|
|
2161
|
-
})
|
|
2162
|
-
.searchListener(dt)
|
|
2163
|
-
.title(dt
|
|
2164
|
-
.i18n('columnControl.searchList', config.title)
|
|
2165
|
-
.replace('[title]', dt.column(this.idx()).title()))
|
|
2166
|
-
.handler(function (e, btn, btns, redraw) {
|
|
2167
|
-
if (btn) {
|
|
2168
|
-
btn.active(!btn.active());
|
|
2169
|
-
}
|
|
2170
|
-
applySearch(checkList.values());
|
|
2171
|
-
if (redraw) {
|
|
2172
|
-
dt.draw();
|
|
2173
|
-
}
|
|
2174
|
-
});
|
|
2175
|
-
if (config.options) {
|
|
2176
|
-
setOptions(checkList, config.options);
|
|
2177
|
-
}
|
|
2178
|
-
else {
|
|
2179
|
-
dt.ready(function () {
|
|
2180
|
-
reloadOptions(dt, config, _this.idx(), checkList, loadedValues);
|
|
2181
|
-
});
|
|
2182
|
-
// Xhr event listener for updates of options
|
|
2183
|
-
dt.on('xhr', function (e, s, json) {
|
|
2184
|
-
// Need to wait for the draw to complete so the table has the latest data
|
|
2185
|
-
dt.one('draw', function () {
|
|
2186
|
-
reloadOptions(dt, config, _this.idx(), checkList, loadedValues);
|
|
2187
|
-
});
|
|
2188
|
-
});
|
|
2189
|
-
}
|
|
2190
|
-
// Data for server-side processing
|
|
2191
|
-
if (dt.page.info().serverSide) {
|
|
2192
|
-
dt.on('preXhr.DT', function (e, s, d) {
|
|
2193
|
-
// The column has been removed from the submit data - can't do anything
|
|
2194
|
-
if (!d.columns || !d.columns[_this.idx()]) {
|
|
2195
|
-
return;
|
|
2196
|
-
}
|
|
2197
|
-
if (!d.columns[_this.idx()].columnControl) {
|
|
2198
|
-
d.columns[_this.idx()].columnControl = {};
|
|
2199
|
-
}
|
|
2200
|
-
// We need the indexes in the HTTP parameter names (for .NET), so use an object.
|
|
2201
|
-
d.columns[_this.idx()].columnControl.list = Object.assign({}, checkList.values());
|
|
2202
|
-
});
|
|
2203
|
-
}
|
|
2204
|
-
// Unlike the SearchInput based search contents, CheckList does not handle state saving
|
|
2205
|
-
// (since the mechanism for column visibility is different), so state saving is handled
|
|
2206
|
-
// here.
|
|
2207
|
-
dt.on('stateLoaded', function (e, s, state) {
|
|
2208
|
-
var values = getState(_this.idx(), state);
|
|
2209
|
-
if (values) {
|
|
2210
|
-
checkList.values(values);
|
|
2211
|
-
applySearch(values);
|
|
2212
|
-
}
|
|
2213
|
-
});
|
|
2214
|
-
dt.on('stateSaveParams', function (e, s, data) {
|
|
2215
|
-
var idx = _this.idx();
|
|
2216
|
-
if (!data.columnControl) {
|
|
2217
|
-
data.columnControl = {};
|
|
2218
|
-
}
|
|
2219
|
-
if (!data.columnControl[idx]) {
|
|
2220
|
-
data.columnControl[idx] = {};
|
|
2221
|
-
}
|
|
2222
|
-
// If the table isn't yet ready, then the options for the list won't have been
|
|
2223
|
-
// populated (above) and therefore there can't be an values. In such a case
|
|
2224
|
-
// use the last saved values and this will refresh on the next draw.
|
|
2225
|
-
data.columnControl[idx].searchList = dt.ready()
|
|
2226
|
-
? checkList.values()
|
|
2227
|
-
: loadedValues;
|
|
2228
|
-
});
|
|
2229
|
-
dt.settings()[0].aoColumns[this.idx()].columnControlSearchList = function (options) {
|
|
2230
|
-
if (options === 'refresh') {
|
|
2231
|
-
reloadOptions(dt, config, _this.idx(), checkList, null);
|
|
2232
|
-
}
|
|
2233
|
-
else {
|
|
2234
|
-
setOptions(checkList, options);
|
|
2235
|
-
}
|
|
2236
|
-
};
|
|
2237
|
-
loadedValues = getState(this.idx(), dt.state.loaded());
|
|
2238
|
-
applySearch(loadedValues);
|
|
2239
|
-
return checkList.element();
|
|
2240
|
-
}
|
|
2241
|
-
};
|
|
2242
|
-
|
|
2243
|
-
var searchNumber = {
|
|
2244
|
-
defaults: {
|
|
2245
|
-
clear: true,
|
|
2246
|
-
placeholder: '',
|
|
2247
|
-
title: '',
|
|
2248
|
-
titleAttr: ''
|
|
2249
|
-
},
|
|
2250
|
-
init: function (config) {
|
|
2251
|
-
var _this = this;
|
|
2252
|
-
var dt = this.dt();
|
|
2253
|
-
var i18nBase = 'columnControl.search.number.';
|
|
2254
|
-
var searchInput = new SearchInput(dt, this.idx())
|
|
2255
|
-
.type('num')
|
|
2256
|
-
.addClass('dtcc-searchNumber')
|
|
2257
|
-
.clearable(config.clear)
|
|
2258
|
-
.placeholder(config.placeholder)
|
|
2259
|
-
.title(config.title)
|
|
2260
|
-
.titleAttr(config.titleAttr)
|
|
2261
|
-
.options([
|
|
2262
|
-
{ label: dt.i18n(i18nBase + 'equal', 'Equals'), value: 'equal' },
|
|
2263
|
-
{ label: dt.i18n(i18nBase + 'notEqual', 'Does not equal'), value: 'notEqual' },
|
|
2264
|
-
{ label: dt.i18n(i18nBase + 'greater', 'Greater than'), value: 'greater' },
|
|
2265
|
-
{
|
|
2266
|
-
label: dt.i18n(i18nBase + 'greaterOrEqual', 'Greater or equal'),
|
|
2267
|
-
value: 'greaterOrEqual'
|
|
2268
|
-
},
|
|
2269
|
-
{ label: dt.i18n(i18nBase + 'less', 'Less than'), value: 'less' },
|
|
2270
|
-
{ label: dt.i18n(i18nBase + 'lessOrEqual', 'Less or equal'), value: 'lessOrEqual' },
|
|
2271
|
-
{ label: dt.i18n(i18nBase + 'empty', 'Empty'), value: 'empty' },
|
|
2272
|
-
{ label: dt.i18n(i18nBase + 'notEmpty', 'Not empty'), value: 'notEmpty' }
|
|
2273
|
-
])
|
|
2274
|
-
.search(function (searchType, searchTerm, loadingState) {
|
|
2275
|
-
// When SSP, don't apply a filter here, SearchInput will add to the submit data
|
|
2276
|
-
if (dt.page.info().serverSide) {
|
|
2277
|
-
if (!loadingState) {
|
|
2278
|
-
dt.draw();
|
|
2279
|
-
}
|
|
2280
|
-
return;
|
|
2281
|
-
}
|
|
2282
|
-
var column = dt.column(_this.idx());
|
|
2283
|
-
if (searchType === 'empty') {
|
|
2284
|
-
column.search.fixed('dtcc', function (haystack) { return !haystack; });
|
|
2285
|
-
}
|
|
2286
|
-
else if (searchType === 'notEmpty') {
|
|
2287
|
-
column.search.fixed('dtcc', function (haystack) { return !!haystack; });
|
|
2288
|
-
}
|
|
2289
|
-
else if (column.search.fixed('dtcc') === '' && searchTerm === '') {
|
|
2290
|
-
// No change - don't do anything
|
|
2291
|
-
return;
|
|
2292
|
-
}
|
|
2293
|
-
else if (searchTerm === '') {
|
|
2294
|
-
// Clear search
|
|
2295
|
-
column.search.fixed('dtcc', '');
|
|
2296
|
-
}
|
|
2297
|
-
else if (searchType === 'equal') {
|
|
2298
|
-
// Use a function for matching - weak typing
|
|
2299
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) == searchTerm; });
|
|
2300
|
-
}
|
|
2301
|
-
else if (searchType === 'notEqual') {
|
|
2302
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) != searchTerm; });
|
|
2303
|
-
}
|
|
2304
|
-
else if (searchType === 'greater') {
|
|
2305
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) > searchTerm; });
|
|
2306
|
-
}
|
|
2307
|
-
else if (searchType === 'greaterOrEqual') {
|
|
2308
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) >= searchTerm; });
|
|
2309
|
-
}
|
|
2310
|
-
else if (searchType === 'less') {
|
|
2311
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) < searchTerm; });
|
|
2312
|
-
}
|
|
2313
|
-
else if (searchType === 'lessOrEqual') {
|
|
2314
|
-
column.search.fixed('dtcc', function (haystack) { return stringToNum(haystack) <= searchTerm; });
|
|
2315
|
-
}
|
|
2316
|
-
// If in a dropdown, set the parents as active
|
|
2317
|
-
if (config._parents) {
|
|
2318
|
-
config._parents.forEach(function (btn) {
|
|
2319
|
-
return btn.activeList(_this.unique(), !!column.search.fixed('dtcc'));
|
|
2320
|
-
});
|
|
2321
|
-
}
|
|
2322
|
-
if (!loadingState) {
|
|
2323
|
-
column.draw();
|
|
2324
|
-
}
|
|
2325
|
-
});
|
|
2326
|
-
// Set a numeric input type, per BBC's guidelines
|
|
2327
|
-
searchInput.input().setAttribute('inputmode', 'numeric');
|
|
2328
|
-
searchInput.input().setAttribute('pattern', '[0-9]*');
|
|
2329
|
-
return searchInput.element();
|
|
2330
|
-
}
|
|
2331
|
-
};
|
|
2332
|
-
var _re_html = /<([^>]*>)/g;
|
|
2333
|
-
var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
|
|
2334
|
-
function stringToNum(d) {
|
|
2335
|
-
if (d !== 0 && (!d || d === '-')) {
|
|
2336
|
-
return -Infinity;
|
|
2337
|
-
}
|
|
2338
|
-
var type = typeof d;
|
|
2339
|
-
if (type === 'number' || type === 'bigint') {
|
|
2340
|
-
return d;
|
|
2341
|
-
}
|
|
2342
|
-
if (d.replace) {
|
|
2343
|
-
d = d.replace(_re_html, '').replace(_re_formatted_numeric, '');
|
|
2344
|
-
}
|
|
2345
|
-
return d * 1;
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2348
|
-
var searchText = {
|
|
2349
|
-
defaults: {
|
|
2350
|
-
clear: true,
|
|
2351
|
-
placeholder: '',
|
|
2352
|
-
title: '',
|
|
2353
|
-
titleAttr: ''
|
|
2354
|
-
},
|
|
2355
|
-
init: function (config) {
|
|
2356
|
-
var _this = this;
|
|
2357
|
-
var dt = this.dt();
|
|
2358
|
-
var i18nBase = 'columnControl.search.text.';
|
|
2359
|
-
var searchInput = new SearchInput(dt, this.idx())
|
|
2360
|
-
.addClass('dtcc-searchText')
|
|
2361
|
-
.clearable(config.clear)
|
|
2362
|
-
.placeholder(config.placeholder)
|
|
2363
|
-
.title(config.title)
|
|
2364
|
-
.titleAttr(config.titleAttr)
|
|
2365
|
-
.options([
|
|
2366
|
-
{ label: dt.i18n(i18nBase + 'contains', 'Contains'), value: 'contains' },
|
|
2367
|
-
{
|
|
2368
|
-
label: dt.i18n(i18nBase + 'notContains', 'Does not contain'),
|
|
2369
|
-
value: 'notContains'
|
|
2370
|
-
},
|
|
2371
|
-
{ label: dt.i18n(i18nBase + 'equal', 'Equals'), value: 'equal' },
|
|
2372
|
-
{ label: dt.i18n(i18nBase + 'notEqual', 'Does not equal'), value: 'notEqual' },
|
|
2373
|
-
{ label: dt.i18n(i18nBase + 'starts', 'Starts'), value: 'starts' },
|
|
2374
|
-
{ label: dt.i18n(i18nBase + 'ends', 'Ends'), value: 'ends' },
|
|
2375
|
-
{ label: dt.i18n(i18nBase + 'empty', 'Empty'), value: 'empty' },
|
|
2376
|
-
{ label: dt.i18n(i18nBase + 'notEmpty', 'Not empty'), value: 'notEmpty' }
|
|
2377
|
-
])
|
|
2378
|
-
.search(function (searchType, searchTerm, loadingState) {
|
|
2379
|
-
// When SSP, don't apply a filter here, SearchInput will add to the submit data
|
|
2380
|
-
if (dt.page.info().serverSide) {
|
|
2381
|
-
if (!loadingState) {
|
|
2382
|
-
dt.draw();
|
|
2383
|
-
}
|
|
2384
|
-
return;
|
|
2385
|
-
}
|
|
2386
|
-
var column = dt.column(_this.idx());
|
|
2387
|
-
searchTerm = searchTerm.toLowerCase();
|
|
2388
|
-
if (searchType === 'empty') {
|
|
2389
|
-
column.search.fixed('dtcc', function (haystack) { return !haystack; });
|
|
2390
|
-
}
|
|
2391
|
-
else if (searchType === 'notEmpty') {
|
|
2392
|
-
column.search.fixed('dtcc', function (haystack) { return !!haystack; });
|
|
2393
|
-
}
|
|
2394
|
-
else if (column.search.fixed('dtcc') === '' && searchTerm === '') {
|
|
2395
|
-
// No change - don't do anything
|
|
2396
|
-
return;
|
|
2397
|
-
}
|
|
2398
|
-
else if (searchTerm === '') {
|
|
2399
|
-
// Clear search
|
|
2400
|
-
column.search.fixed('dtcc', '');
|
|
2401
|
-
}
|
|
2402
|
-
else if (searchType === 'equal') {
|
|
2403
|
-
// Use a function for exact matching
|
|
2404
|
-
column.search.fixed('dtcc', function (haystack) { return haystack.toLowerCase() == searchTerm; });
|
|
2405
|
-
}
|
|
2406
|
-
else if (searchType === 'notEqual') {
|
|
2407
|
-
column.search.fixed('dtcc', function (haystack) { return haystack.toLowerCase() != searchTerm; });
|
|
2408
|
-
}
|
|
2409
|
-
else if (searchType === 'contains') {
|
|
2410
|
-
// Use the built in smart search
|
|
2411
|
-
column.search.fixed('dtcc', searchTerm);
|
|
2412
|
-
}
|
|
2413
|
-
else if (searchType === 'notContains') {
|
|
2414
|
-
// Use the built in smart search
|
|
2415
|
-
column.search.fixed('dtcc', function (haystack) { return !haystack.toLowerCase().includes(searchTerm); });
|
|
2416
|
-
}
|
|
2417
|
-
else if (searchType === 'starts') {
|
|
2418
|
-
// Use a function for startsWith case insensitive search
|
|
2419
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
2420
|
-
return haystack.toLowerCase().startsWith(searchTerm);
|
|
2421
|
-
});
|
|
2422
|
-
}
|
|
2423
|
-
else if (searchType === 'ends') {
|
|
2424
|
-
column.search.fixed('dtcc', function (haystack) {
|
|
2425
|
-
return haystack.toLowerCase().endsWith(searchTerm);
|
|
2426
|
-
});
|
|
2427
|
-
}
|
|
2428
|
-
// If in a dropdown, set the parent levels as active
|
|
2429
|
-
if (config._parents) {
|
|
2430
|
-
config._parents.forEach(function (btn) {
|
|
2431
|
-
return btn.activeList(_this.unique(), !!column.search.fixed('dtcc'));
|
|
2432
|
-
});
|
|
2433
|
-
}
|
|
2434
|
-
if (!loadingState) {
|
|
2435
|
-
column.draw();
|
|
2436
|
-
}
|
|
2437
|
-
});
|
|
2438
|
-
return searchInput.element();
|
|
2439
|
-
}
|
|
2440
|
-
};
|
|
2441
|
-
|
|
2442
|
-
var search = {
|
|
2443
|
-
defaults: {
|
|
2444
|
-
allowSearchList: false
|
|
2445
|
-
},
|
|
2446
|
-
init: function (config) {
|
|
2447
|
-
var _this = this;
|
|
2448
|
-
var _a, _b, _c;
|
|
2449
|
-
var dt = this.dt();
|
|
2450
|
-
var idx = this.idx();
|
|
2451
|
-
var displayEl;
|
|
2452
|
-
var loadedState = (_c = (_b = (_a = dt.state.loaded()) === null || _a === void 0 ? void 0 : _a.columnControl) === null || _b === void 0 ? void 0 : _b[idx]) === null || _c === void 0 ? void 0 : _c.searchInput;
|
|
2453
|
-
var initType = function (type) {
|
|
2454
|
-
var json = getJsonOptions(dt, idx);
|
|
2455
|
-
// Attempt to match what type of search should be shown
|
|
2456
|
-
if (config.allowSearchList && json) {
|
|
2457
|
-
// We've got a list of JSON options, and are allowed to show the searchList
|
|
2458
|
-
return searchList.init.call(_this, Object.assign({}, searchList.defaults, config));
|
|
2459
|
-
}
|
|
2460
|
-
else if (type === 'date' || type.startsWith('datetime')) {
|
|
2461
|
-
// Date types
|
|
2462
|
-
return searchDateTime.init.call(_this, Object.assign({}, searchDateTime.defaults, config));
|
|
2463
|
-
}
|
|
2464
|
-
else if (type.includes('num')) {
|
|
2465
|
-
// Number types
|
|
2466
|
-
return searchNumber.init.call(_this, Object.assign({}, searchNumber.defaults, config));
|
|
2467
|
-
}
|
|
2468
|
-
else {
|
|
2469
|
-
// Everything else
|
|
2470
|
-
return searchText.init.call(_this, Object.assign({}, searchText.defaults, config));
|
|
2471
|
-
}
|
|
2472
|
-
};
|
|
2473
|
-
// If we know the type from the saved state, we can load it immediately. This is required
|
|
2474
|
-
// to allow the state to be applied to the table and the first draw to have a filter
|
|
2475
|
-
// applied (if it is needed).
|
|
2476
|
-
if (loadedState) {
|
|
2477
|
-
displayEl = initType(loadedState.type);
|
|
2478
|
-
}
|
|
2479
|
-
else {
|
|
2480
|
-
// Wait until we can get the data type for the column and the run the corresponding type
|
|
2481
|
-
displayEl = document.createElement('div');
|
|
2482
|
-
dt.ready(function () {
|
|
2483
|
-
var column = dt.column(idx);
|
|
2484
|
-
var display = initType(column.type());
|
|
2485
|
-
displayEl.replaceWith(display);
|
|
2486
|
-
});
|
|
2487
|
-
}
|
|
2488
|
-
return displayEl;
|
|
2489
|
-
}
|
|
2490
|
-
};
|
|
2491
|
-
|
|
2492
|
-
var searchClear$1 = {
|
|
2493
|
-
defaults: {
|
|
2494
|
-
className: 'searchClear',
|
|
2495
|
-
icon: 'searchClear',
|
|
2496
|
-
text: 'Clear Search'
|
|
2497
|
-
},
|
|
2498
|
-
init: function (config) {
|
|
2499
|
-
var _this = this;
|
|
2500
|
-
var dt = this.dt();
|
|
2501
|
-
var btn = new Button(dt, this)
|
|
2502
|
-
.text(dt.i18n('columnControl.searchClear', config.text))
|
|
2503
|
-
.icon(config.icon)
|
|
2504
|
-
.className(config.className)
|
|
2505
|
-
.handler(function () {
|
|
2506
|
-
dt.column(_this.idx()).columnControl.searchClear().draw();
|
|
2507
|
-
})
|
|
2508
|
-
.enable(false);
|
|
2509
|
-
dt.on('draw', function () {
|
|
2510
|
-
// change enable state
|
|
2511
|
-
var search = dt.column(_this.idx()).search.fixed('dtcc');
|
|
2512
|
-
var searchList = dt.column(_this.idx()).search.fixed('dtcc-list');
|
|
2513
|
-
btn.enable(!!(search || searchList));
|
|
2514
|
-
});
|
|
2515
|
-
return btn.element();
|
|
2516
|
-
}
|
|
2517
|
-
};
|
|
2518
|
-
|
|
2519
|
-
var searchDropdown = {
|
|
2520
|
-
defaults: {
|
|
2521
|
-
ajaxOnly: true,
|
|
2522
|
-
allowSearchList: true,
|
|
2523
|
-
className: 'searchDropdown',
|
|
2524
|
-
clear: true,
|
|
2525
|
-
columns: '',
|
|
2526
|
-
hidable: true,
|
|
2527
|
-
options: null,
|
|
2528
|
-
orthogonal: 'display',
|
|
2529
|
-
placeholder: '',
|
|
2530
|
-
search: true,
|
|
2531
|
-
select: true,
|
|
2532
|
-
text: 'Search',
|
|
2533
|
-
title: '',
|
|
2534
|
-
titleAttr: ''
|
|
2535
|
-
},
|
|
2536
|
-
extend: function (config) {
|
|
2537
|
-
var dt = this.dt();
|
|
2538
|
-
return {
|
|
2539
|
-
extend: 'dropdown',
|
|
2540
|
-
icon: 'search',
|
|
2541
|
-
text: dt.i18n('columnControl.searchDropdown', config.text),
|
|
2542
|
-
content: [
|
|
2543
|
-
Object.assign(config, {
|
|
2544
|
-
extend: 'search'
|
|
2545
|
-
})
|
|
2546
|
-
]
|
|
2547
|
-
};
|
|
2548
|
-
}
|
|
2549
|
-
};
|
|
2550
|
-
|
|
2551
|
-
var spacer = {
|
|
2552
|
-
defaults: {
|
|
2553
|
-
className: 'dtcc-spacer',
|
|
2554
|
-
text: ''
|
|
2555
|
-
},
|
|
2556
|
-
init: function (config) {
|
|
2557
|
-
var dt = this.dt();
|
|
2558
|
-
var spacer = createElement('div', config.className, dt.i18n('columnControl.spacer', config.text));
|
|
2559
|
-
spacer.setAttribute('role', 'separator');
|
|
2560
|
-
return spacer;
|
|
2561
|
-
}
|
|
2562
|
-
};
|
|
2563
|
-
|
|
2564
|
-
var title = {
|
|
2565
|
-
defaults: {
|
|
2566
|
-
className: 'dtcc-title',
|
|
2567
|
-
text: null
|
|
2568
|
-
},
|
|
2569
|
-
init: function (config) {
|
|
2570
|
-
var dt = this.dt();
|
|
2571
|
-
var title = dt.column(this.idx()).title();
|
|
2572
|
-
var text = config.text === null ? '[title]' : config.text;
|
|
2573
|
-
var el = createElement('div', config.className, text.replace('[title]', title));
|
|
2574
|
-
return el;
|
|
2575
|
-
}
|
|
2576
|
-
};
|
|
2577
|
-
|
|
2578
|
-
var contentTypes = {
|
|
2579
|
-
colVis: colVis,
|
|
2580
|
-
colVisDropdown: colVisDropdown,
|
|
2581
|
-
dropdown: dropdownContent,
|
|
2582
|
-
reorder: reorder,
|
|
2583
|
-
reorderLeft: reorderLeft,
|
|
2584
|
-
reorderRight: reorderRight,
|
|
2585
|
-
rowGroup: rowGroup,
|
|
2586
|
-
rowGroupAdd: rowGroupAdd,
|
|
2587
|
-
rowGroupClear: rowGroupClear,
|
|
2588
|
-
rowGroupRemove: rowGroupRemove,
|
|
2589
|
-
order: order,
|
|
2590
|
-
orderAddAsc: orderAddAsc,
|
|
2591
|
-
orderAddDesc: orderAddDesc,
|
|
2592
|
-
orderAsc: orderAsc,
|
|
2593
|
-
orderClear: orderClear,
|
|
2594
|
-
orderDesc: orderDesc,
|
|
2595
|
-
orderRemove: orderRemove,
|
|
2596
|
-
orderStatus: orderStatus,
|
|
2597
|
-
search: search,
|
|
2598
|
-
searchClear: searchClear$1,
|
|
2599
|
-
searchDropdown: searchDropdown,
|
|
2600
|
-
searchDateTime: searchDateTime,
|
|
2601
|
-
searchList: searchList,
|
|
2602
|
-
searchNumber: searchNumber,
|
|
2603
|
-
searchText: searchText,
|
|
2604
|
-
spacer: spacer,
|
|
2605
|
-
title: title
|
|
2606
|
-
};
|
|
2607
|
-
|
|
2608
|
-
/**
|
|
2609
|
-
*
|
|
2610
|
-
*/
|
|
2611
|
-
var ColumnControl = /** @class */ (function () {
|
|
2612
|
-
/**
|
|
2613
|
-
* Create a new ColumnControl instance to control a DataTables column.
|
|
2614
|
-
*
|
|
2615
|
-
* @param dt DataTables API instance
|
|
2616
|
-
* @param columnIdx Column index to operation on
|
|
2617
|
-
* @param opts Configuration options
|
|
2618
|
-
*/
|
|
2619
|
-
function ColumnControl(dt, columnIdx, opts) {
|
|
2620
|
-
var _this = this;
|
|
2621
|
-
this._dom = {
|
|
2622
|
-
target: null,
|
|
2623
|
-
wrapper: null
|
|
2624
|
-
};
|
|
2625
|
-
this._c = {};
|
|
2626
|
-
this._s = {
|
|
2627
|
-
columnIdx: null,
|
|
2628
|
-
unique: null,
|
|
2629
|
-
toDestroy: []
|
|
2630
|
-
};
|
|
2631
|
-
this._dt = dt;
|
|
2632
|
-
this._s.columnIdx = columnIdx;
|
|
2633
|
-
this._s.unique = Math.random();
|
|
2634
|
-
var originalIdx = columnIdx;
|
|
2635
|
-
Object.assign(this._c, ColumnControl.defaults, opts);
|
|
2636
|
-
this._dom.target = this._target();
|
|
2637
|
-
if (opts.className) {
|
|
2638
|
-
addClass(this._dom.target.closest('tr'), opts.className);
|
|
2639
|
-
}
|
|
2640
|
-
if (this._c.content) {
|
|
2641
|
-
// If column reordering can be done, we reassign the column index here, and before the
|
|
2642
|
-
// plugins can add their own listeners.
|
|
2643
|
-
dt.on('columns-reordered', function (e, details) {
|
|
2644
|
-
_this._s.columnIdx = dt.colReorder.transpose(originalIdx, 'fromOriginal');
|
|
2645
|
-
});
|
|
2646
|
-
this._dom.wrapper = document.createElement('span');
|
|
2647
|
-
this._dom.wrapper.classList.add('dtcc');
|
|
2648
|
-
this._dom.target.appendChild(this._dom.wrapper);
|
|
2649
|
-
this._c.content.forEach(function (content) {
|
|
2650
|
-
var _a = _this.resolve(content), plugin = _a.plugin, config = _a.config;
|
|
2651
|
-
var el = plugin.init.call(_this, config);
|
|
2652
|
-
_this._dom.wrapper.appendChild(el);
|
|
2653
|
-
});
|
|
2654
|
-
dt.on('destroy', function () {
|
|
2655
|
-
_this._s.toDestroy.slice().forEach(function (el) {
|
|
2656
|
-
el.destroy();
|
|
2657
|
-
});
|
|
2658
|
-
_this._dom.wrapper.remove();
|
|
2659
|
-
});
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
/**
|
|
2663
|
-
* Add a component to the destroy list. This is so there is a single destroy event handler,
|
|
2664
|
-
* which is much better for performance.
|
|
2665
|
-
*
|
|
2666
|
-
* @param component Any instance with a `destroy` method
|
|
2667
|
-
*/
|
|
2668
|
-
ColumnControl.prototype.destroyAdd = function (component) {
|
|
2669
|
-
this._s.toDestroy.push(component);
|
|
2670
|
-
};
|
|
2671
|
-
/**
|
|
2672
|
-
* Remove an instance from the destroy list (it has been destroyed itself)
|
|
2673
|
-
*
|
|
2674
|
-
* @param component Any instance with a `destroy` method
|
|
2675
|
-
*/
|
|
2676
|
-
ColumnControl.prototype.destroyRemove = function (component) {
|
|
2677
|
-
var idx = this._s.toDestroy.indexOf(component);
|
|
2678
|
-
if (idx !== -1) {
|
|
2679
|
-
this._s.toDestroy.splice(idx, 1);
|
|
2680
|
-
}
|
|
2681
|
-
};
|
|
2682
|
-
/**
|
|
2683
|
-
* Get the DataTables API instance that hosts this instance of ColumnControl
|
|
2684
|
-
*
|
|
2685
|
-
* @returns DataTables API instance
|
|
2686
|
-
*/
|
|
2687
|
-
ColumnControl.prototype.dt = function () {
|
|
2688
|
-
return this._dt;
|
|
2689
|
-
};
|
|
2690
|
-
/**
|
|
2691
|
-
* Get what column index this instance of ColumnControl is operating on
|
|
2692
|
-
*
|
|
2693
|
-
* @returns Column index
|
|
2694
|
-
*/
|
|
2695
|
-
ColumnControl.prototype.idx = function () {
|
|
2696
|
-
return this._s.columnIdx;
|
|
2697
|
-
};
|
|
2698
|
-
/**
|
|
2699
|
-
* Covert the options from `content` in the DataTable initialisation for this instance into a
|
|
2700
|
-
* resolved plugin and options.
|
|
2701
|
-
*
|
|
2702
|
-
* @param content The dev's supplied configuration for the content
|
|
2703
|
-
* @returns Resolved plugin information
|
|
2704
|
-
*/
|
|
2705
|
-
ColumnControl.prototype.resolve = function (content) {
|
|
2706
|
-
var plugin = null;
|
|
2707
|
-
var config = null;
|
|
2708
|
-
var type = null;
|
|
2709
|
-
if (typeof content === 'string') {
|
|
2710
|
-
// Simple content - uses default options
|
|
2711
|
-
type = content;
|
|
2712
|
-
plugin = ColumnControl.content[type];
|
|
2713
|
-
config = Object.assign({}, plugin === null || plugin === void 0 ? void 0 : plugin.defaults);
|
|
2714
|
-
}
|
|
2715
|
-
else if (Array.isArray(content)) {
|
|
2716
|
-
// An array is a shorthand for a dropdown with its default options
|
|
2717
|
-
type = 'dropdown';
|
|
2718
|
-
plugin = ColumnControl.content[type];
|
|
2719
|
-
config = Object.assign({}, plugin === null || plugin === void 0 ? void 0 : plugin.defaults, {
|
|
2720
|
-
content: content
|
|
2721
|
-
});
|
|
2722
|
-
}
|
|
2723
|
-
else if (content.extend) {
|
|
2724
|
-
// Content with custom options
|
|
2725
|
-
type = content.extend;
|
|
2726
|
-
plugin = ColumnControl.content[type];
|
|
2727
|
-
config = Object.assign({}, plugin === null || plugin === void 0 ? void 0 : plugin.defaults, content);
|
|
2728
|
-
}
|
|
2729
|
-
if (!plugin) {
|
|
2730
|
-
throw new Error('Unknown ColumnControl content type: ' + type);
|
|
2731
|
-
}
|
|
2732
|
-
// If the plugin is a wrapper around another type - e.g. the colVisDropdown
|
|
2733
|
-
if (plugin.extend) {
|
|
2734
|
-
var self_1 = plugin.extend.call(this, config);
|
|
2735
|
-
return this.resolve(self_1);
|
|
2736
|
-
}
|
|
2737
|
-
return {
|
|
2738
|
-
config: config,
|
|
2739
|
-
type: type,
|
|
2740
|
-
plugin: plugin
|
|
2741
|
-
};
|
|
2742
|
-
};
|
|
2743
|
-
/**
|
|
2744
|
-
* Get the unique id for the instance
|
|
2745
|
-
*
|
|
2746
|
-
* @returns Instant unique id
|
|
2747
|
-
*/
|
|
2748
|
-
ColumnControl.prototype.unique = function () {
|
|
2749
|
-
return this._s.unique;
|
|
2750
|
-
};
|
|
2751
|
-
/**
|
|
2752
|
-
* Resolve the configured target into a DOM element
|
|
2753
|
-
*/
|
|
2754
|
-
ColumnControl.prototype._target = function () {
|
|
2755
|
-
var target = this._c.target;
|
|
2756
|
-
var column = this._dt.column(this._s.columnIdx);
|
|
2757
|
-
var node;
|
|
2758
|
-
var className = 'header';
|
|
2759
|
-
// Header row index
|
|
2760
|
-
if (typeof target === 'number') {
|
|
2761
|
-
node = column.header(target);
|
|
2762
|
-
}
|
|
2763
|
-
else {
|
|
2764
|
-
var parts = target.split(':');
|
|
2765
|
-
var isHeader = parts[0] === 'tfoot' ? false : true;
|
|
2766
|
-
var row = parts[1] ? parseInt(parts[1]) : 0;
|
|
2767
|
-
if (isHeader) {
|
|
2768
|
-
node = column.header(row);
|
|
2769
|
-
}
|
|
2770
|
-
else {
|
|
2771
|
-
node = column.footer(row);
|
|
2772
|
-
className = 'footer';
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
2775
|
-
return node.querySelector('div.dt-column-' + className);
|
|
2776
|
-
};
|
|
2777
|
-
// Classes for common UI
|
|
2778
|
-
ColumnControl.Button = Button;
|
|
2779
|
-
ColumnControl.CheckList = CheckList;
|
|
2780
|
-
ColumnControl.SearchInput = SearchInput;
|
|
2781
|
-
/** Content plugins */
|
|
2782
|
-
ColumnControl.content = contentTypes;
|
|
2783
|
-
/** Defaults for ColumnControl */
|
|
2784
|
-
ColumnControl.defaults = {
|
|
2785
|
-
className: '',
|
|
2786
|
-
content: null,
|
|
2787
|
-
target: 0,
|
|
2788
|
-
};
|
|
2789
|
-
/** SVG icons that can be used by the content plugins */
|
|
2790
|
-
ColumnControl.icons = icons;
|
|
2791
|
-
/** Version */
|
|
2792
|
-
ColumnControl.version = '1.1.1';
|
|
2793
|
-
return ColumnControl;
|
|
2794
|
-
}());
|
|
2795
|
-
|
|
2796
|
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2797
|
-
* DataTables API integration
|
|
2798
|
-
*/
|
|
2799
|
-
DataTable.ColumnControl = ColumnControl;
|
|
2800
|
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2801
|
-
* DataTables listeners for initialisation
|
|
2802
|
-
*/
|
|
2803
|
-
// Create header / footer rows that don't exist, but have been referenced in the ColumnControl
|
|
2804
|
-
// targets. This needs to be done _before_ the header / footer structure is detected.
|
|
2805
|
-
$(document).on('i18n.dt', function (e, settings) {
|
|
2806
|
-
if (e.namespace !== 'dt') {
|
|
2807
|
-
return;
|
|
2808
|
-
}
|
|
2809
|
-
var api = new DataTable.Api(settings);
|
|
2810
|
-
var thead = api.table().header();
|
|
2811
|
-
var tableInit = settings.oInit.columnControl;
|
|
2812
|
-
var defaultInit = ColumnControl.defaults;
|
|
2813
|
-
var baseTargets = [];
|
|
2814
|
-
var ackTargets = {};
|
|
2815
|
-
// Determine if there is only one header row initially. If there is, we might append more
|
|
2816
|
-
// after it. Mark the top row as the header row using `titleRow` in the DataTables configuration
|
|
2817
|
-
if (thead.querySelectorAll('tr').length <= 1 && settings.titleRow === null) {
|
|
2818
|
-
settings.titleRow = 0;
|
|
2819
|
-
}
|
|
2820
|
-
identifyTargets(baseTargets, tableInit);
|
|
2821
|
-
if (ColumnControl.defaults.content) {
|
|
2822
|
-
identifyTargets(baseTargets, defaultInit);
|
|
2823
|
-
}
|
|
2824
|
-
api.columns().every(function (i) {
|
|
2825
|
-
var columnInit = this.init().columnControl;
|
|
2826
|
-
identifyTargets(baseTargets, columnInit);
|
|
2827
|
-
});
|
|
2828
|
-
for (var i = 0; i < baseTargets.length; i++) {
|
|
2829
|
-
assetTarget(ackTargets, baseTargets[i], api);
|
|
2830
|
-
}
|
|
2831
|
-
});
|
|
2832
|
-
// Initialisation of ColumnControl instances - has to be done _after_ the header / footer structure
|
|
2833
|
-
// is detected by DataTables.
|
|
2834
|
-
$(document).on('preInit.dt', function (e, settings) {
|
|
2835
|
-
if (e.namespace !== 'dt') {
|
|
2836
|
-
return;
|
|
2837
|
-
}
|
|
2838
|
-
var api = new DataTable.Api(settings);
|
|
2839
|
-
var tableInit = settings.oInit.columnControl;
|
|
2840
|
-
var defaultInit = ColumnControl.defaults;
|
|
2841
|
-
var baseTargets = [];
|
|
2842
|
-
identifyTargets(baseTargets, tableInit);
|
|
2843
|
-
// Only add the default target if there is actually content for it
|
|
2844
|
-
if (ColumnControl.defaults.content) {
|
|
2845
|
-
identifyTargets(baseTargets, defaultInit);
|
|
2846
|
-
}
|
|
2847
|
-
api.columns().every(function (i) {
|
|
2848
|
-
var columnInit = this.init().columnControl;
|
|
2849
|
-
var targets = identifyTargets(baseTargets.slice(), columnInit);
|
|
2850
|
-
for (var i_1 = 0; i_1 < targets.length; i_1++) {
|
|
2851
|
-
// Each of the column, table and defaults configuration can be an array of config
|
|
2852
|
-
// objects, an array of content, or a configuration object. There might be multiple
|
|
2853
|
-
// targets for each one, and they might not exist! Therefore this is more complex
|
|
2854
|
-
// than it might be desirable.
|
|
2855
|
-
var columnTargetInit = getOptionsForTarget(targets[i_1], columnInit);
|
|
2856
|
-
var tableTargetInit = getOptionsForTarget(targets[i_1], tableInit);
|
|
2857
|
-
var defaultTargetInit = getOptionsForTarget(targets[i_1], defaultInit);
|
|
2858
|
-
if (defaultTargetInit || tableTargetInit || columnTargetInit) {
|
|
2859
|
-
new ColumnControl(api, this.index(), Object.assign({}, defaultTargetInit || {}, tableTargetInit || {}, columnTargetInit || {}));
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
});
|
|
2863
|
-
});
|
|
2864
|
-
function searchClear() {
|
|
2865
|
-
var ctx = this;
|
|
2866
|
-
return this.iterator('column', function (settings, idx) {
|
|
2867
|
-
// Note that the listeners for this will not redraw the table.
|
|
2868
|
-
ctx.trigger('cc-search-clear', [idx]);
|
|
2869
|
-
});
|
|
2870
|
-
}
|
|
2871
|
-
DataTable.Api.registerPlural('columns().columnControl.searchClear()', 'column().columnControl.searchClear()', searchClear);
|
|
2872
|
-
// Legacy (1.0.x)) - was never documented, but was mentioned in the forum
|
|
2873
|
-
DataTable.Api.registerPlural('columns().ccSearchClear()', 'column().ccSearchClear()', searchClear);
|
|
2874
|
-
DataTable.Api.registerPlural('columns().columnControl.searchList()', 'column().columnControl.searchList()', function (options) {
|
|
2875
|
-
return this.iterator('column', function (settings, idx) {
|
|
2876
|
-
var fn = settings.aoColumns[idx].columnControlSearchList;
|
|
2877
|
-
if (fn) {
|
|
2878
|
-
fn(options);
|
|
2879
|
-
}
|
|
2880
|
-
});
|
|
2881
|
-
});
|
|
2882
|
-
DataTable.ext.buttons.ccSearchClear = {
|
|
2883
|
-
text: function (dt) {
|
|
2884
|
-
return dt.i18n('columnControl.buttons.searchClear', 'Clear search');
|
|
2885
|
-
},
|
|
2886
|
-
init: function (dt, node, config) {
|
|
2887
|
-
var _this = this;
|
|
2888
|
-
dt.on('draw.DT', function () {
|
|
2889
|
-
var enabled = false;
|
|
2890
|
-
var glob = !!dt.search();
|
|
2891
|
-
// No point in wasting clock cycles if we already know it will be enabled
|
|
2892
|
-
if (!glob) {
|
|
2893
|
-
dt.columns().every(function () {
|
|
2894
|
-
if (this.search.fixed('dtcc') || this.search.fixed('dtcc-list')) {
|
|
2895
|
-
enabled = true;
|
|
2896
|
-
}
|
|
2897
|
-
});
|
|
2898
|
-
}
|
|
2899
|
-
_this.enable(glob || enabled);
|
|
2900
|
-
});
|
|
2901
|
-
this.enable(false);
|
|
2902
|
-
},
|
|
2903
|
-
action: function (e, dt, node, config) {
|
|
2904
|
-
dt.search('');
|
|
2905
|
-
dt.columns().columnControl.searchClear();
|
|
2906
|
-
dt.draw();
|
|
2907
|
-
}
|
|
2908
|
-
};
|
|
2909
|
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2910
|
-
* Initialisation support - this is more involved than normal as targets might
|
|
2911
|
-
* need to be created, and also options needs to be resolved into a standard
|
|
2912
|
-
* ColumnControl configuration object, from the various forms allowed in the
|
|
2913
|
-
* DataTables configuration.
|
|
2914
|
-
*/
|
|
2915
|
-
/**
|
|
2916
|
-
* Given a ColumnControl target, make sure that it exists. If not, create it.
|
|
2917
|
-
*
|
|
2918
|
-
* @param ackTargets Cache for list of targets that have already been found or created
|
|
2919
|
-
* @param target Current target
|
|
2920
|
-
* @param dt DataTable API
|
|
2921
|
-
* @returns Void
|
|
2922
|
-
*/
|
|
2923
|
-
function assetTarget(ackTargets, target, dt) {
|
|
2924
|
-
// Check if we already know about the target - if so, we know that it must already be in place
|
|
2925
|
-
if (ackTargets[target]) {
|
|
2926
|
-
return;
|
|
2927
|
-
}
|
|
2928
|
-
var isHeader = true; // false for footer
|
|
2929
|
-
var row = 0;
|
|
2930
|
-
if (typeof target === 'number') {
|
|
2931
|
-
row = target;
|
|
2932
|
-
}
|
|
2933
|
-
else {
|
|
2934
|
-
var parts = target.split(':');
|
|
2935
|
-
if (parts[0] === 'tfoot') {
|
|
2936
|
-
isHeader = false;
|
|
2937
|
-
}
|
|
2938
|
-
if (parts[1]) {
|
|
2939
|
-
row = parseInt(parts[1]);
|
|
2940
|
-
}
|
|
2941
|
-
}
|
|
2942
|
-
// The header / footer have not yet had their structure read, so they aren't available via
|
|
2943
|
-
// the API. As such we need to do our own DOM tweaking
|
|
2944
|
-
var node = isHeader ? dt.table().header() : dt.table().footer();
|
|
2945
|
-
// If the node doesn't exist yet, we need to create it
|
|
2946
|
-
if (!node.querySelectorAll('tr')[row]) {
|
|
2947
|
-
var columns = dt.columns().count();
|
|
2948
|
-
var tr = createElement('tr');
|
|
2949
|
-
tr.setAttribute('data-dt-order', 'disable');
|
|
2950
|
-
for (var i = 0; i < columns; i++) {
|
|
2951
|
-
tr.appendChild(createElement('td'));
|
|
2952
|
-
}
|
|
2953
|
-
node.appendChild(tr);
|
|
2954
|
-
}
|
|
2955
|
-
ackTargets[target] = true;
|
|
2956
|
-
}
|
|
2957
|
-
/**
|
|
2958
|
-
* Given a target, get the config object for it from the parameter passed in
|
|
2959
|
-
*
|
|
2960
|
-
* @param target ColumnControl target
|
|
2961
|
-
* @param input The dev's configuration
|
|
2962
|
-
* @returns The resolved config object, if found
|
|
2963
|
-
*/
|
|
2964
|
-
function getOptionsForTarget(target, input) {
|
|
2965
|
-
var defaultTarget = ColumnControl.defaults.target;
|
|
2966
|
-
var selfTarget;
|
|
2967
|
-
if (isIContentArray(input)) {
|
|
2968
|
-
// Top level content array - e.g. `columnControl: ['order']`
|
|
2969
|
-
if (defaultTarget === target) {
|
|
2970
|
-
return {
|
|
2971
|
-
target: defaultTarget,
|
|
2972
|
-
content: input
|
|
2973
|
-
};
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
|
-
else if (Array.isArray(input)) {
|
|
2977
|
-
// Top level array, some items of which will be configuration objects (possibly not all)
|
|
2978
|
-
for (var i = 0; i < input.length; i++) {
|
|
2979
|
-
var item = input[i];
|
|
2980
|
-
if (isIContentArray(item)) {
|
|
2981
|
-
// A content array, e.g. the inner array from: `columnControl: [['order']]
|
|
2982
|
-
if (defaultTarget === target) {
|
|
2983
|
-
return {
|
|
2984
|
-
target: defaultTarget,
|
|
2985
|
-
content: item
|
|
2986
|
-
};
|
|
2987
|
-
}
|
|
2988
|
-
}
|
|
2989
|
-
else if (isIConfig(item)) {
|
|
2990
|
-
// A config object, e.g. the object from: `columnControl: [{content: []}]`
|
|
2991
|
-
selfTarget = item.target !== undefined ? item.target : defaultTarget;
|
|
2992
|
-
if (target === selfTarget) {
|
|
2993
|
-
return item;
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
else {
|
|
2997
|
-
// A content object
|
|
2998
|
-
if (target === defaultTarget) {
|
|
2999
|
-
return {
|
|
3000
|
-
target: defaultTarget,
|
|
3001
|
-
content: input
|
|
3002
|
-
};
|
|
3003
|
-
}
|
|
3004
|
-
}
|
|
3005
|
-
}
|
|
3006
|
-
}
|
|
3007
|
-
else if (typeof input === 'object') {
|
|
3008
|
-
// An object can be either a config object, or an extending content object
|
|
3009
|
-
if (isIConfig(input)) {
|
|
3010
|
-
// Config object: columnControl: {content: []}
|
|
3011
|
-
selfTarget = input.target !== undefined ? input.target : defaultTarget;
|
|
3012
|
-
if (target === selfTarget) {
|
|
3013
|
-
return input;
|
|
3014
|
-
}
|
|
3015
|
-
}
|
|
3016
|
-
else {
|
|
3017
|
-
// content object: columnControl: [{extend: 'order'}]
|
|
3018
|
-
if (target === defaultTarget) {
|
|
3019
|
-
return {
|
|
3020
|
-
target: defaultTarget,
|
|
3021
|
-
content: input
|
|
3022
|
-
};
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
}
|
|
3026
|
-
}
|
|
3027
|
-
/**
|
|
3028
|
-
* Get a list of all targets from the configuration objects / arrays
|
|
3029
|
-
*
|
|
3030
|
-
* @param targets Established list of targets - mutated
|
|
3031
|
-
* @param input Configuration object / array
|
|
3032
|
-
* @returns Updated array
|
|
3033
|
-
*/
|
|
3034
|
-
function identifyTargets(targets, input) {
|
|
3035
|
-
function add(target) {
|
|
3036
|
-
if (!targets.includes(target)) {
|
|
3037
|
-
targets.push(target);
|
|
3038
|
-
}
|
|
3039
|
-
}
|
|
3040
|
-
if (Array.isArray(input)) {
|
|
3041
|
-
if (input.length === 0) {
|
|
3042
|
-
// Empty array - assume it is empty content
|
|
3043
|
-
add(ColumnControl.defaults.target);
|
|
3044
|
-
}
|
|
3045
|
-
else {
|
|
3046
|
-
// Array of options, or an array of content
|
|
3047
|
-
input.forEach(function (item) {
|
|
3048
|
-
add(typeof item === 'object' && item.target !== undefined
|
|
3049
|
-
? item.target
|
|
3050
|
-
: ColumnControl.defaults.target);
|
|
3051
|
-
});
|
|
3052
|
-
}
|
|
3053
|
-
}
|
|
3054
|
-
else if (typeof input === 'object') {
|
|
3055
|
-
// Full options defined: { target: x, content: [] }
|
|
3056
|
-
add(input.target !== undefined ? input.target : ColumnControl.defaults.target);
|
|
3057
|
-
}
|
|
3058
|
-
return targets;
|
|
3059
|
-
}
|
|
3060
|
-
/**
|
|
3061
|
-
* Check if an item is a configuration object or not
|
|
3062
|
-
*
|
|
3063
|
-
* @param item Item to check
|
|
3064
|
-
* @returns true if it is a config object
|
|
3065
|
-
*/
|
|
3066
|
-
function isIConfig(item) {
|
|
3067
|
-
return typeof item === 'object' && item.target !== undefined ? true : false;
|
|
3068
|
-
}
|
|
3069
|
-
/**
|
|
3070
|
-
* Determine if an array contains only content items or not
|
|
3071
|
-
*
|
|
3072
|
-
* @param arr Array to check
|
|
3073
|
-
* @returns true if is content only, false if not (i.e. is an array with configuration objects).
|
|
3074
|
-
*/
|
|
3075
|
-
function isIContentArray(arr) {
|
|
3076
|
-
var detectedConfig = false;
|
|
3077
|
-
if (!Array.isArray(arr)) {
|
|
3078
|
-
return false;
|
|
3079
|
-
}
|
|
3080
|
-
for (var i = 0; i < arr.length; i++) {
|
|
3081
|
-
if (isIConfig(arr[i])) {
|
|
3082
|
-
detectedConfig = true;
|
|
3083
|
-
break;
|
|
3084
|
-
}
|
|
3085
|
-
}
|
|
3086
|
-
return !detectedConfig;
|
|
3087
|
-
}
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
return DataTable;
|
|
3091
|
-
}));
|