@atlassian/aui 9.4.6-0c8cd15d6 → 9.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aui/aui-prototyping-browserfocus.css +2 -0
- package/dist/aui/aui-prototyping-darkmode.css +2 -0
- package/dist/aui/aui-prototyping.css +7 -7
- package/dist/aui/aui-prototyping.css.map +1 -1
- package/dist/aui/aui-prototyping.js +17 -34
- package/dist/aui/aui-prototyping.js.map +1 -1
- package/dist/aui/aui-prototyping.nodeps.css +7 -7
- package/dist/aui/aui-prototyping.nodeps.css.map +1 -1
- package/dist/aui/aui-prototyping.nodeps.js +20 -37
- package/dist/aui/aui-prototyping.nodeps.js.map +1 -1
- package/entry/aui.batch.components.js +2 -0
- package/entry/aui.component.avatar-group.js +4 -0
- package/entry/aui.component.avatar.js +5 -0
- package/package.json +10 -10
- package/src/js/aui/avatar-badged.js +38 -0
- package/src/js/aui/avatar-group.js +165 -0
- package/src/js/aui/avatar.js +76 -0
- package/src/js/aui/blanket.js +1 -1
- package/src/js/aui/internal/header/create-header.js +2 -0
- package/src/js/aui/messages.js +18 -2
- package/src/js/aui/tooltip.js +2 -4
- package/src/js/aui/when-i-type.js +14 -3
- package/src/js-vendor/jquery/jquery.tablesorter.js +2663 -1645
- package/src/less/aui-avatars.less +101 -0
- package/src/less/imports/aui-theme/core/colors.less +8 -0
|
@@ -1,1896 +1,2914 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
/*! TableSorter (FORK) v2.31.3 *//*
|
|
2
|
+
* Client-side table sorting with ease!
|
|
3
|
+
* @requires jQuery v1.2.6+
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2007 Christian Bach
|
|
6
|
+
* fork maintained by Rob Garrison
|
|
7
|
+
*
|
|
8
|
+
* Examples and original docs at: http://tablesorter.com
|
|
9
|
+
* Dual licensed under the MIT and GPL licenses:
|
|
10
|
+
* http://www.opensource.org/licenses/mit-license.php
|
|
11
|
+
* http://www.gnu.org/licenses/gpl.html
|
|
12
|
+
*
|
|
13
|
+
* @type jQuery
|
|
14
|
+
* @name tablesorter (FORK)
|
|
15
|
+
* @cat Plugins/Tablesorter
|
|
16
|
+
* @author Christian Bach - christian.bach@polyester.se
|
|
17
|
+
* @contributor Rob Garrison - https://github.com/Mottie/tablesorter
|
|
18
|
+
* @docs (fork) - https://mottie.github.io/tablesorter/docs/
|
|
19
|
+
*/
|
|
17
20
|
/*jshint browser:true, jquery:true, unused:false, expr: true */
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
21
|
+
;( function( $ ) {
|
|
22
|
+
'use strict';
|
|
23
|
+
var ts = $.tablesorter = {
|
|
24
|
+
|
|
25
|
+
version : '2.31.3',
|
|
26
|
+
|
|
27
|
+
parsers : [],
|
|
28
|
+
widgets : [],
|
|
29
|
+
defaults : {
|
|
30
|
+
|
|
31
|
+
// *** appearance
|
|
32
|
+
theme : 'default', // adds tablesorter-{theme} to the table for styling
|
|
33
|
+
widthFixed : false, // adds colgroup to fix widths of columns
|
|
34
|
+
showProcessing : false, // show an indeterminate timer icon in the header when the table is sorted or filtered.
|
|
35
|
+
|
|
36
|
+
headerTemplate : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = <i></i> // class from cssIcon
|
|
37
|
+
onRenderTemplate : null, // function( index, template ) { return template; }, // template is a string
|
|
38
|
+
onRenderHeader : null, // function( index ) {}, // nothing to return
|
|
39
|
+
|
|
40
|
+
// *** functionality
|
|
41
|
+
cancelSelection : true, // prevent text selection in the header
|
|
42
|
+
tabIndex : true, // add tabindex to header for keyboard accessibility
|
|
43
|
+
dateFormat : 'mmddyyyy', // other options: 'ddmmyyy' or 'yyyymmdd'
|
|
44
|
+
sortMultiSortKey : 'shiftKey', // key used to select additional columns
|
|
45
|
+
sortResetKey : 'ctrlKey', // key used to remove sorting on a column
|
|
46
|
+
usNumberFormat : true, // false for German '1.234.567,89' or French '1 234 567,89'
|
|
47
|
+
delayInit : false, // if false, the parsed table contents will not update until the first sort
|
|
48
|
+
serverSideSorting: false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used.
|
|
49
|
+
resort : true, // default setting to trigger a resort after an 'update', 'addRows', 'updateCell', etc has completed
|
|
50
|
+
|
|
51
|
+
// *** sort options
|
|
52
|
+
headers : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc.
|
|
53
|
+
ignoreCase : true, // ignore case while sorting
|
|
54
|
+
sortForce : null, // column(s) first sorted; always applied
|
|
55
|
+
sortList : [], // Initial sort order; applied initially; updated when manually sorted
|
|
56
|
+
sortAppend : null, // column(s) sorted last; always applied
|
|
57
|
+
sortStable : false, // when sorting two rows with exactly the same content, the original sort order is maintained
|
|
58
|
+
|
|
59
|
+
sortInitialOrder : 'asc', // sort direction on first click
|
|
60
|
+
sortLocaleCompare: false, // replace equivalent character (accented characters)
|
|
61
|
+
sortReset : false, // third click on the header will reset column to default - unsorted
|
|
62
|
+
sortRestart : false, // restart sort to 'sortInitialOrder' when clicking on previously unsorted columns
|
|
63
|
+
|
|
64
|
+
emptyTo : 'bottom', // sort empty cell to bottom, top, none, zero, emptyMax, emptyMin
|
|
65
|
+
stringTo : 'max', // sort strings in numerical column as max, min, top, bottom, zero
|
|
66
|
+
duplicateSpan : true, // colspan cells in the tbody will have duplicated content in the cache for each spanned column
|
|
67
|
+
textExtraction : 'basic', // text extraction method/function - function( node, table, cellIndex ) {}
|
|
68
|
+
textAttribute : 'data-text',// data-attribute that contains alternate cell text (used in default textExtraction function)
|
|
69
|
+
textSorter : null, // choose overall or specific column sorter function( a, b, direction, table, columnIndex ) [alt: ts.sortText]
|
|
70
|
+
numberSorter : null, // choose overall numeric sorter function( a, b, direction, maxColumnValue )
|
|
71
|
+
|
|
72
|
+
// *** widget options
|
|
73
|
+
initWidgets : true, // apply widgets on tablesorter initialization
|
|
74
|
+
widgetClass : 'widget-{name}', // table class name template to match to include a widget
|
|
75
|
+
widgets : [], // method to add widgets, e.g. widgets: ['zebra']
|
|
76
|
+
widgetOptions : {
|
|
77
|
+
zebra : [ 'even', 'odd' ] // zebra widget alternating row class names
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// *** callbacks
|
|
81
|
+
initialized : null, // function( table ) {},
|
|
82
|
+
|
|
83
|
+
// *** extra css class names
|
|
84
|
+
tableClass : '',
|
|
85
|
+
cssAsc : '',
|
|
86
|
+
cssDesc : '',
|
|
87
|
+
cssNone : '',
|
|
88
|
+
cssHeader : '',
|
|
89
|
+
cssHeaderRow : '',
|
|
90
|
+
cssProcessing : '', // processing icon applied to header during sort/filter
|
|
91
|
+
|
|
92
|
+
cssChildRow : 'tablesorter-childRow', // class name indiciating that a row is to be attached to its parent
|
|
93
|
+
cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!)
|
|
94
|
+
cssNoSort : 'tablesorter-noSort', // class name added to element inside header; clicking on it won't cause a sort
|
|
95
|
+
cssIgnoreRow : 'tablesorter-ignoreRow',// header row to ignore; cells within this row will not be added to c.$headers
|
|
96
|
+
|
|
97
|
+
cssIcon : 'tablesorter-icon', // if this class does not exist, the {icon} will not be added from the headerTemplate
|
|
98
|
+
cssIconNone : '', // class name added to the icon when there is no column sort
|
|
99
|
+
cssIconAsc : '', // class name added to the icon when the column has an ascending sort
|
|
100
|
+
cssIconDesc : '', // class name added to the icon when the column has a descending sort
|
|
101
|
+
cssIconDisabled : '', // class name added to the icon when the column has a disabled sort
|
|
102
|
+
|
|
103
|
+
// *** events
|
|
104
|
+
pointerClick : 'click',
|
|
105
|
+
pointerDown : 'mousedown',
|
|
106
|
+
pointerUp : 'mouseup',
|
|
107
|
+
|
|
108
|
+
// *** selectors
|
|
109
|
+
selectorHeaders : '> thead th, > thead td',
|
|
110
|
+
selectorSort : 'th, td', // jQuery selector of content within selectorHeaders that is clickable to trigger a sort
|
|
111
|
+
selectorRemove : '.remove-me',
|
|
112
|
+
|
|
113
|
+
// *** advanced
|
|
114
|
+
debug : false,
|
|
115
|
+
|
|
116
|
+
// *** Internal variables
|
|
117
|
+
headerList: [],
|
|
118
|
+
empties: {},
|
|
119
|
+
strings: {},
|
|
120
|
+
parsers: [],
|
|
121
|
+
|
|
122
|
+
// *** parser options for validator; values must be falsy!
|
|
123
|
+
globalize: 0,
|
|
124
|
+
imgAttr: 0
|
|
125
|
+
|
|
126
|
+
// removed: widgetZebra: { css: ['even', 'odd'] }
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
// widgetZebra: { css: ["even", "odd"] }
|
|
128
|
+
},
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
// internal css classes - these will ALWAYS be added to
|
|
131
|
+
// the table and MUST only contain one class name - fixes #381
|
|
132
|
+
css : {
|
|
133
|
+
table : 'tablesorter',
|
|
134
|
+
cssHasChild: 'tablesorter-hasChildRow',
|
|
135
|
+
childRow : 'tablesorter-childRow',
|
|
136
|
+
colgroup : 'tablesorter-colgroup',
|
|
137
|
+
header : 'tablesorter-header',
|
|
138
|
+
headerRow : 'tablesorter-headerRow',
|
|
139
|
+
headerIn : 'tablesorter-header-inner',
|
|
140
|
+
icon : 'tablesorter-icon',
|
|
141
|
+
processing : 'tablesorter-processing',
|
|
142
|
+
sortAsc : 'tablesorter-headerAsc',
|
|
143
|
+
sortDesc : 'tablesorter-headerDesc',
|
|
144
|
+
sortNone : 'tablesorter-headerUnSorted'
|
|
145
|
+
},
|
|
113
146
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
info : 'tablesorter-infoOnly',
|
|
125
|
-
processing : 'tablesorter-processing',
|
|
126
|
-
sortAsc : 'tablesorter-headerAsc',
|
|
127
|
-
sortDesc : 'tablesorter-headerDesc',
|
|
128
|
-
sortNone : 'tablesorter-headerUnSorted'
|
|
129
|
-
};
|
|
147
|
+
// labels applied to sortable headers for accessibility (aria) support
|
|
148
|
+
language : {
|
|
149
|
+
sortAsc : 'Ascending sort applied, ',
|
|
150
|
+
sortDesc : 'Descending sort applied, ',
|
|
151
|
+
sortNone : 'No sort applied, ',
|
|
152
|
+
sortDisabled : 'sorting is disabled',
|
|
153
|
+
nextAsc : 'activate to apply an ascending sort',
|
|
154
|
+
nextDesc : 'activate to apply a descending sort',
|
|
155
|
+
nextNone : 'activate to remove the sort'
|
|
156
|
+
},
|
|
130
157
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
nextNone : 'activate to remove the sort'
|
|
139
|
-
};
|
|
158
|
+
regex : {
|
|
159
|
+
templateContent : /\{content\}/g,
|
|
160
|
+
templateIcon : /\{icon\}/g,
|
|
161
|
+
templateName : /\{name\}/i,
|
|
162
|
+
spaces : /\s+/g,
|
|
163
|
+
nonWord : /\W/g,
|
|
164
|
+
formElements : /(input|select|button|textarea)/i,
|
|
140
165
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
166
|
+
// *** sort functions ***
|
|
167
|
+
// regex used in natural sort
|
|
168
|
+
// chunk/tokenize numbers & letters
|
|
169
|
+
chunk : /(^([+\-]?(?:\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,
|
|
170
|
+
// replace chunks @ ends
|
|
171
|
+
chunks : /(^\\0|\\0$)/,
|
|
172
|
+
hex : /^0x[0-9a-f]+$/i,
|
|
173
|
+
|
|
174
|
+
// *** formatFloat ***
|
|
175
|
+
comma : /,/g,
|
|
176
|
+
digitNonUS : /[\s|\.]/g,
|
|
177
|
+
digitNegativeTest : /^\s*\([.\d]+\)/,
|
|
178
|
+
digitNegativeReplace : /^\s*\(([.\d]+)\)/,
|
|
179
|
+
|
|
180
|
+
// *** isDigit ***
|
|
181
|
+
digitTest : /^[\-+(]?\d+[)]?$/,
|
|
182
|
+
digitReplace : /[,.'"\s]/g
|
|
183
|
+
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// digit sort, text location
|
|
187
|
+
string : {
|
|
188
|
+
max : 1,
|
|
189
|
+
min : -1,
|
|
190
|
+
emptymin : 1,
|
|
191
|
+
emptymax : -1,
|
|
192
|
+
zero : 0,
|
|
193
|
+
none : 0,
|
|
194
|
+
'null' : 0,
|
|
195
|
+
top : true,
|
|
196
|
+
bottom : false
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
keyCodes : {
|
|
200
|
+
enter : 13
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
// placeholder date parser data (globalize)
|
|
204
|
+
dates : {},
|
|
205
|
+
|
|
206
|
+
// These methods can be applied on table.config instance
|
|
207
|
+
instanceMethods : {},
|
|
208
|
+
|
|
209
|
+
/*
|
|
210
|
+
▄█████ ██████ ██████ ██ ██ █████▄
|
|
211
|
+
▀█▄ ██▄▄ ██ ██ ██ ██▄▄██
|
|
212
|
+
▀█▄ ██▀▀ ██ ██ ██ ██▀▀▀
|
|
213
|
+
█████▀ ██████ ██ ▀████▀ ██
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
setup : function( table, c ) {
|
|
217
|
+
// if no thead or tbody, or tablesorter is already present, quit
|
|
218
|
+
if ( !table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true ) {
|
|
219
|
+
if ( ts.debug(c, 'core') ) {
|
|
220
|
+
if ( table.hasInitialized ) {
|
|
221
|
+
console.warn( 'Stopping initialization. Tablesorter has already been initialized' );
|
|
222
|
+
} else {
|
|
223
|
+
console.error( 'Stopping initialization! No table, thead or tbody', table );
|
|
224
|
+
}
|
|
149
225
|
}
|
|
226
|
+
return;
|
|
150
227
|
}
|
|
151
228
|
|
|
152
|
-
|
|
153
|
-
|
|
229
|
+
var tmp = '',
|
|
230
|
+
$table = $( table ),
|
|
231
|
+
meta = $.metadata;
|
|
232
|
+
// initialization flag
|
|
233
|
+
table.hasInitialized = false;
|
|
234
|
+
// table is being processed flag
|
|
235
|
+
table.isProcessing = true;
|
|
236
|
+
// make sure to store the config object
|
|
237
|
+
table.config = c;
|
|
238
|
+
// save the settings where they read
|
|
239
|
+
$.data( table, 'tablesorter', c );
|
|
240
|
+
if ( ts.debug(c, 'core') ) {
|
|
241
|
+
console[ console.group ? 'group' : 'log' ]( 'Initializing tablesorter v' + ts.version );
|
|
242
|
+
$.data( table, 'startoveralltimer', new Date() );
|
|
154
243
|
}
|
|
155
244
|
|
|
156
|
-
|
|
157
|
-
|
|
245
|
+
// removing this in version 3 (only supports jQuery 1.7+)
|
|
246
|
+
c.supportsDataObject = ( function( version ) {
|
|
247
|
+
version[ 0 ] = parseInt( version[ 0 ], 10 );
|
|
248
|
+
return ( version[ 0 ] > 1 ) || ( version[ 0 ] === 1 && parseInt( version[ 1 ], 10 ) >= 4 );
|
|
249
|
+
})( $.fn.jquery.split( '.' ) );
|
|
250
|
+
// ensure case insensitivity
|
|
251
|
+
c.emptyTo = c.emptyTo.toLowerCase();
|
|
252
|
+
c.stringTo = c.stringTo.toLowerCase();
|
|
253
|
+
c.last = { sortList : [], clickedIndex : -1 };
|
|
254
|
+
// add table theme class only if there isn't already one there
|
|
255
|
+
if ( !/tablesorter\-/.test( $table.attr( 'class' ) ) ) {
|
|
256
|
+
tmp = ( c.theme !== '' ? ' tablesorter-' + c.theme : '' );
|
|
257
|
+
}
|
|
158
258
|
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return true;
|
|
259
|
+
// give the table a unique id, which will be used in namespace binding
|
|
260
|
+
if ( !c.namespace ) {
|
|
261
|
+
c.namespace = '.tablesorter' + Math.random().toString( 16 ).slice( 2 );
|
|
262
|
+
} else {
|
|
263
|
+
// make sure namespace starts with a period & doesn't have weird characters
|
|
264
|
+
c.namespace = '.' + c.namespace.replace( ts.regex.nonWord, '' );
|
|
166
265
|
}
|
|
167
266
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
267
|
+
c.table = table;
|
|
268
|
+
c.$table = $table
|
|
269
|
+
// add namespace to table to allow bindings on extra elements to target
|
|
270
|
+
// the parent table (e.g. parser-input-select)
|
|
271
|
+
.addClass( ts.css.table + ' ' + c.tableClass + tmp + ' ' + c.namespace.slice(1) )
|
|
272
|
+
.attr( 'role', 'grid' );
|
|
273
|
+
c.$headers = $table.find( c.selectorHeaders );
|
|
274
|
+
|
|
275
|
+
c.$table.children().children( 'tr' ).attr( 'role', 'row' );
|
|
276
|
+
c.$tbodies = $table.children( 'tbody:not(.' + c.cssInfoBlock + ')' ).attr({
|
|
277
|
+
'aria-live' : 'polite',
|
|
278
|
+
'aria-relevant' : 'all'
|
|
279
|
+
});
|
|
280
|
+
if ( c.$table.children( 'caption' ).length ) {
|
|
281
|
+
tmp = c.$table.children( 'caption' )[ 0 ];
|
|
282
|
+
if ( !tmp.id ) { tmp.id = c.namespace.slice( 1 ) + 'caption'; }
|
|
283
|
+
c.$table.attr( 'aria-labelledby', tmp.id );
|
|
284
|
+
}
|
|
285
|
+
c.widgetInit = {}; // keep a list of initialized widgets
|
|
286
|
+
// change textExtraction via data-attribute
|
|
287
|
+
c.textExtraction = c.$table.attr( 'data-text-extraction' ) || c.textExtraction || 'basic';
|
|
288
|
+
// build headers
|
|
289
|
+
ts.buildHeaders( c );
|
|
290
|
+
// fixate columns if the users supplies the fixedWidth option
|
|
291
|
+
// do this after theme has been applied
|
|
292
|
+
ts.fixColumnWidth( table );
|
|
293
|
+
// add widgets from class name
|
|
294
|
+
ts.addWidgetFromClass( table );
|
|
295
|
+
// add widget options before parsing (e.g. grouping widget has parser settings)
|
|
296
|
+
ts.applyWidgetOptions( table );
|
|
297
|
+
// try to auto detect column type, and store in tables config
|
|
298
|
+
ts.setupParsers( c );
|
|
299
|
+
// start total row count at zero
|
|
300
|
+
c.totalRows = 0;
|
|
301
|
+
// only validate options while debugging. See #1528
|
|
302
|
+
if (c.debug) {
|
|
303
|
+
ts.validateOptions( c );
|
|
304
|
+
}
|
|
305
|
+
// build the cache for the tbody cells
|
|
306
|
+
// delayInit will delay building the cache until the user starts a sort
|
|
307
|
+
if ( !c.delayInit ) { ts.buildCache( c ); }
|
|
308
|
+
// bind all header events and methods
|
|
309
|
+
ts.bindEvents( table, c.$headers, true );
|
|
310
|
+
ts.bindMethods( c );
|
|
311
|
+
// get sort list from jQuery data or metadata
|
|
312
|
+
// in jQuery < 1.4, an error occurs when calling $table.data()
|
|
313
|
+
if ( c.supportsDataObject && typeof $table.data().sortlist !== 'undefined' ) {
|
|
314
|
+
c.sortList = $table.data().sortlist;
|
|
315
|
+
} else if ( meta && ( $table.metadata() && $table.metadata().sortlist ) ) {
|
|
316
|
+
c.sortList = $table.metadata().sortlist;
|
|
317
|
+
}
|
|
318
|
+
// apply widget init code
|
|
319
|
+
ts.applyWidget( table, true );
|
|
320
|
+
// if user has supplied a sort list to constructor
|
|
321
|
+
if ( c.sortList.length > 0 ) {
|
|
322
|
+
// save sortList before any sortAppend is added
|
|
323
|
+
c.last.sortList = c.sortList;
|
|
324
|
+
ts.sortOn( c, c.sortList, {}, !c.initWidgets );
|
|
325
|
+
} else {
|
|
326
|
+
ts.setHeadersCss( c );
|
|
327
|
+
if ( c.initWidgets ) {
|
|
328
|
+
// apply widget format
|
|
329
|
+
ts.applyWidget( table, false );
|
|
185
330
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
nodeValue = getElementText(table, node, cellIndex);
|
|
200
|
-
if (table.config.debug) {
|
|
201
|
-
log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// show processesing icon
|
|
334
|
+
if ( c.showProcessing ) {
|
|
335
|
+
$table
|
|
336
|
+
.unbind( 'sortBegin' + c.namespace + ' sortEnd' + c.namespace )
|
|
337
|
+
.bind( 'sortBegin' + c.namespace + ' sortEnd' + c.namespace, function( e ) {
|
|
338
|
+
clearTimeout( c.timerProcessing );
|
|
339
|
+
ts.isProcessing( table );
|
|
340
|
+
if ( e.type === 'sortBegin' ) {
|
|
341
|
+
c.timerProcessing = setTimeout( function() {
|
|
342
|
+
ts.isProcessing( table, true );
|
|
343
|
+
}, 500 );
|
|
202
344
|
}
|
|
203
|
-
}
|
|
204
|
-
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// initialized
|
|
349
|
+
table.hasInitialized = true;
|
|
350
|
+
table.isProcessing = false;
|
|
351
|
+
if ( ts.debug(c, 'core') ) {
|
|
352
|
+
console.log( 'Overall initialization time:' + ts.benchmark( $.data( table, 'startoveralltimer' ) ) );
|
|
353
|
+
if ( ts.debug(c, 'core') && console.groupEnd ) { console.groupEnd(); }
|
|
354
|
+
}
|
|
355
|
+
$table.triggerHandler( 'tablesorter-initialized', table );
|
|
356
|
+
if ( typeof c.initialized === 'function' ) {
|
|
357
|
+
c.initialized( table );
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
bindMethods : function( c ) {
|
|
362
|
+
var $table = c.$table,
|
|
363
|
+
namespace = c.namespace,
|
|
364
|
+
events = ( 'sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete ' +
|
|
365
|
+
'sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup ' +
|
|
366
|
+
'mouseleave ' ).split( ' ' )
|
|
367
|
+
.join( namespace + ' ' );
|
|
368
|
+
// apply easy methods that trigger bound events
|
|
369
|
+
$table
|
|
370
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
|
371
|
+
.bind( 'sortReset' + namespace, function( e, callback ) {
|
|
372
|
+
e.stopPropagation();
|
|
373
|
+
// using this.config to ensure functions are getting a non-cached version of the config
|
|
374
|
+
ts.sortReset( this.config, function( table ) {
|
|
375
|
+
if (table.isApplyingWidgets) {
|
|
376
|
+
// multiple triggers in a row... filterReset, then sortReset - see #1361
|
|
377
|
+
// wait to update widgets
|
|
378
|
+
setTimeout( function() {
|
|
379
|
+
ts.applyWidget( table, '', callback );
|
|
380
|
+
}, 100 );
|
|
381
|
+
} else {
|
|
382
|
+
ts.applyWidget( table, '', callback );
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
})
|
|
386
|
+
.bind( 'updateAll' + namespace, function( e, resort, callback ) {
|
|
387
|
+
e.stopPropagation();
|
|
388
|
+
ts.updateAll( this.config, resort, callback );
|
|
389
|
+
})
|
|
390
|
+
.bind( 'update' + namespace + ' updateRows' + namespace, function( e, resort, callback ) {
|
|
391
|
+
e.stopPropagation();
|
|
392
|
+
ts.update( this.config, resort, callback );
|
|
393
|
+
})
|
|
394
|
+
.bind( 'updateHeaders' + namespace, function( e, callback ) {
|
|
395
|
+
e.stopPropagation();
|
|
396
|
+
ts.updateHeaders( this.config, callback );
|
|
397
|
+
})
|
|
398
|
+
.bind( 'updateCell' + namespace, function( e, cell, resort, callback ) {
|
|
399
|
+
e.stopPropagation();
|
|
400
|
+
ts.updateCell( this.config, cell, resort, callback );
|
|
401
|
+
})
|
|
402
|
+
.bind( 'addRows' + namespace, function( e, $row, resort, callback ) {
|
|
403
|
+
e.stopPropagation();
|
|
404
|
+
ts.addRows( this.config, $row, resort, callback );
|
|
405
|
+
})
|
|
406
|
+
.bind( 'updateComplete' + namespace, function() {
|
|
407
|
+
this.isUpdating = false;
|
|
408
|
+
})
|
|
409
|
+
.bind( 'sorton' + namespace, function( e, list, callback, init ) {
|
|
410
|
+
e.stopPropagation();
|
|
411
|
+
ts.sortOn( this.config, list, callback, init );
|
|
412
|
+
})
|
|
413
|
+
.bind( 'appendCache' + namespace, function( e, callback, init ) {
|
|
414
|
+
e.stopPropagation();
|
|
415
|
+
ts.appendCache( this.config, init );
|
|
416
|
+
if ( $.isFunction( callback ) ) {
|
|
417
|
+
callback( this );
|
|
205
418
|
}
|
|
419
|
+
})
|
|
420
|
+
// $tbodies variable is used by the tbody sorting widget
|
|
421
|
+
.bind( 'updateCache' + namespace, function( e, callback, $tbodies ) {
|
|
422
|
+
e.stopPropagation();
|
|
423
|
+
ts.updateCache( this.config, callback, $tbodies );
|
|
424
|
+
})
|
|
425
|
+
.bind( 'applyWidgetId' + namespace, function( e, id ) {
|
|
426
|
+
e.stopPropagation();
|
|
427
|
+
ts.applyWidgetId( this, id );
|
|
428
|
+
})
|
|
429
|
+
.bind( 'applyWidgets' + namespace, function( e, callback ) {
|
|
430
|
+
e.stopPropagation();
|
|
431
|
+
// apply widgets (false = not initializing)
|
|
432
|
+
ts.applyWidget( this, false, callback );
|
|
433
|
+
})
|
|
434
|
+
.bind( 'refreshWidgets' + namespace, function( e, all, dontapply ) {
|
|
435
|
+
e.stopPropagation();
|
|
436
|
+
ts.refreshWidgets( this, all, dontapply );
|
|
437
|
+
})
|
|
438
|
+
.bind( 'removeWidget' + namespace, function( e, name, refreshing ) {
|
|
439
|
+
e.stopPropagation();
|
|
440
|
+
ts.removeWidget( this, name, refreshing );
|
|
441
|
+
})
|
|
442
|
+
.bind( 'destroy' + namespace, function( e, removeClasses, callback ) {
|
|
443
|
+
e.stopPropagation();
|
|
444
|
+
ts.destroy( this, removeClasses, callback );
|
|
445
|
+
})
|
|
446
|
+
.bind( 'resetToLoadState' + namespace, function( e ) {
|
|
447
|
+
e.stopPropagation();
|
|
448
|
+
// remove all widgets
|
|
449
|
+
ts.removeWidget( this, true, false );
|
|
450
|
+
var tmp = $.extend( true, {}, c.originalSettings );
|
|
451
|
+
// restore original settings; this clears out current settings, but does not clear
|
|
452
|
+
// values saved to storage.
|
|
453
|
+
c = $.extend( true, {}, ts.defaults, tmp );
|
|
454
|
+
c.originalSettings = tmp;
|
|
455
|
+
this.hasInitialized = false;
|
|
456
|
+
// setup the entire table again
|
|
457
|
+
ts.setup( this, c );
|
|
458
|
+
});
|
|
459
|
+
},
|
|
460
|
+
|
|
461
|
+
bindEvents : function( table, $headers, core ) {
|
|
462
|
+
table = $( table )[ 0 ];
|
|
463
|
+
var tmp,
|
|
464
|
+
c = table.config,
|
|
465
|
+
namespace = c.namespace,
|
|
466
|
+
downTarget = null;
|
|
467
|
+
if ( core !== true ) {
|
|
468
|
+
$headers.addClass( namespace.slice( 1 ) + '_extra_headers' );
|
|
469
|
+
tmp = ts.getClosest( $headers, 'table' );
|
|
470
|
+
if ( tmp.length && tmp[ 0 ].nodeName === 'TABLE' && tmp[ 0 ] !== table ) {
|
|
471
|
+
$( tmp[ 0 ] ).addClass( namespace.slice( 1 ) + '_extra_table' );
|
|
206
472
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
473
|
+
}
|
|
474
|
+
tmp = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
|
475
|
+
.replace( ts.regex.spaces, ' ' )
|
|
476
|
+
.split( ' ' )
|
|
477
|
+
.join( namespace + ' ' );
|
|
478
|
+
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
|
479
|
+
$headers
|
|
480
|
+
// http://stackoverflow.com/questions/5312849/jquery-find-self;
|
|
481
|
+
.find( c.selectorSort )
|
|
482
|
+
.add( $headers.filter( c.selectorSort ) )
|
|
483
|
+
.unbind( tmp )
|
|
484
|
+
.bind( tmp, function( e, external ) {
|
|
485
|
+
var $cell, cell, temp,
|
|
486
|
+
$target = $( e.target ),
|
|
487
|
+
// wrap event type in spaces, so the match doesn't trigger on inner words
|
|
488
|
+
type = ' ' + e.type + ' ';
|
|
489
|
+
// only recognize left clicks
|
|
490
|
+
if ( ( ( e.which || e.button ) !== 1 && !type.match( ' ' + c.pointerClick + ' | sort | keyup ' ) ) ||
|
|
491
|
+
// allow pressing enter
|
|
492
|
+
( type === ' keyup ' && e.which !== ts.keyCodes.enter ) ||
|
|
493
|
+
// allow triggering a click event (e.which is undefined) & ignore physical clicks
|
|
494
|
+
( type.match( ' ' + c.pointerClick + ' ' ) && typeof e.which !== 'undefined' ) ) {
|
|
495
|
+
return;
|
|
212
496
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
497
|
+
// ignore mouseup if mousedown wasn't on the same target
|
|
498
|
+
if ( type.match( ' ' + c.pointerUp + ' ' ) && downTarget !== e.target && external !== true ) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
// set target on mousedown
|
|
502
|
+
if ( type.match( ' ' + c.pointerDown + ' ' ) ) {
|
|
503
|
+
downTarget = e.target;
|
|
504
|
+
// preventDefault needed or jQuery v1.3.2 and older throws an
|
|
505
|
+
// "Uncaught TypeError: handler.apply is not a function" error
|
|
506
|
+
temp = $target.jquery.split( '.' );
|
|
507
|
+
if ( temp[ 0 ] === '1' && temp[ 1 ] < 4 ) { e.preventDefault(); }
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
downTarget = null;
|
|
511
|
+
$cell = ts.getClosest( $( this ), '.' + ts.css.header );
|
|
512
|
+
// prevent sort being triggered on form elements
|
|
513
|
+
if ( ts.regex.formElements.test( e.target.nodeName ) ||
|
|
514
|
+
// nosort class name, or elements within a nosort container
|
|
515
|
+
$target.hasClass( c.cssNoSort ) || $target.parents( '.' + c.cssNoSort ).length > 0 ||
|
|
516
|
+
// disabled cell directly clicked
|
|
517
|
+
$cell.hasClass( 'sorter-false' ) ||
|
|
518
|
+
// elements within a button
|
|
519
|
+
$target.parents( 'button' ).length > 0 ) {
|
|
520
|
+
return !c.cancelSelection;
|
|
521
|
+
}
|
|
522
|
+
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
|
|
523
|
+
ts.buildCache( c );
|
|
524
|
+
}
|
|
525
|
+
// use column index from data-attribute or index of current row; fixes #1116
|
|
526
|
+
c.last.clickedIndex = $cell.attr( 'data-column' ) || $cell.index();
|
|
527
|
+
cell = c.$headerIndexed[ c.last.clickedIndex ][0];
|
|
528
|
+
if ( cell && !cell.sortDisabled ) {
|
|
529
|
+
ts.initSort( c, cell, e );
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
if ( c.cancelSelection ) {
|
|
533
|
+
// cancel selection
|
|
534
|
+
$headers
|
|
535
|
+
.attr( 'unselectable', 'on' )
|
|
536
|
+
.bind( 'selectstart', false )
|
|
537
|
+
.css({
|
|
538
|
+
'user-select' : 'none',
|
|
539
|
+
'MozUserSelect' : 'none' // not needed for jQuery 1.8+
|
|
540
|
+
});
|
|
216
541
|
}
|
|
542
|
+
},
|
|
217
543
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
544
|
+
buildHeaders : function( c ) {
|
|
545
|
+
var $temp, icon, timer, indx;
|
|
546
|
+
c.headerList = [];
|
|
547
|
+
c.headerContent = [];
|
|
548
|
+
c.sortVars = [];
|
|
549
|
+
if ( ts.debug(c, 'core') ) {
|
|
550
|
+
timer = new Date();
|
|
551
|
+
}
|
|
552
|
+
// children tr in tfoot - see issue #196 & #547
|
|
553
|
+
// don't pass table.config to computeColumnIndex here - widgets (math) pass it to "quickly" index tbody cells
|
|
554
|
+
c.columns = ts.computeColumnIndex( c.$table.children( 'thead, tfoot' ).children( 'tr' ) );
|
|
555
|
+
// add icon if cssIcon option exists
|
|
556
|
+
icon = c.cssIcon ?
|
|
557
|
+
'<i class="' + ( c.cssIcon === ts.css.icon ? ts.css.icon : c.cssIcon + ' ' + ts.css.icon ) + '"></i>' :
|
|
558
|
+
'';
|
|
559
|
+
// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683
|
|
560
|
+
c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {
|
|
561
|
+
var configHeaders, header, column, template, tmp,
|
|
562
|
+
$elem = $( elem );
|
|
563
|
+
// ignore cell (don't add it to c.$headers) if row has ignoreRow class
|
|
564
|
+
if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; }
|
|
565
|
+
// transfer data-column to element if not th/td - #1459
|
|
566
|
+
if ( !/(th|td)/i.test( elem.nodeName ) ) {
|
|
567
|
+
tmp = ts.getClosest( $elem, 'th, td' );
|
|
568
|
+
$elem.attr( 'data-column', tmp.attr( 'data-column' ) );
|
|
569
|
+
}
|
|
570
|
+
// make sure to get header cell & not column indexed cell
|
|
571
|
+
configHeaders = ts.getColumnData( c.table, c.headers, index, true );
|
|
572
|
+
// save original header content
|
|
573
|
+
c.headerContent[ index ] = $elem.html();
|
|
574
|
+
// if headerTemplate is empty, don't reformat the header cell
|
|
575
|
+
if ( c.headerTemplate !== '' && !$elem.find( '.' + ts.css.headerIn ).length ) {
|
|
576
|
+
// set up header template
|
|
577
|
+
template = c.headerTemplate
|
|
578
|
+
.replace( ts.regex.templateContent, $elem.html() )
|
|
579
|
+
.replace( ts.regex.templateIcon, $elem.find( '.' + ts.css.icon ).length ? '' : icon );
|
|
580
|
+
if ( c.onRenderTemplate ) {
|
|
581
|
+
header = c.onRenderTemplate.apply( $elem, [ index, template ] );
|
|
582
|
+
// only change t if something is returned
|
|
583
|
+
if ( header && typeof header === 'string' ) {
|
|
584
|
+
template = header;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
$elem.html( '<div class="' + ts.css.headerIn + '">' + template + '</div>' ); // faster than wrapInner
|
|
588
|
+
}
|
|
589
|
+
if ( c.onRenderHeader ) {
|
|
590
|
+
c.onRenderHeader.apply( $elem, [ index, c, c.$table ] );
|
|
591
|
+
}
|
|
592
|
+
column = parseInt( $elem.attr( 'data-column' ), 10 );
|
|
593
|
+
elem.column = column;
|
|
594
|
+
tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );
|
|
595
|
+
// this may get updated numerous times if there are multiple rows
|
|
596
|
+
c.sortVars[ column ] = {
|
|
597
|
+
count : -1, // set to -1 because clicking on the header automatically adds one
|
|
598
|
+
order : tmp ?
|
|
599
|
+
( c.sortReset ? [ 1, 0, 2 ] : [ 1, 0 ] ) : // desc, asc, unsorted
|
|
600
|
+
( c.sortReset ? [ 0, 1, 2 ] : [ 0, 1 ] ), // asc, desc, unsorted
|
|
601
|
+
lockedOrder : false,
|
|
602
|
+
sortedBy : ''
|
|
235
603
|
};
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
604
|
+
tmp = ts.getData( $elem, configHeaders, 'lockedOrder' ) || false;
|
|
605
|
+
if ( typeof tmp !== 'undefined' && tmp !== false ) {
|
|
606
|
+
c.sortVars[ column ].lockedOrder = true;
|
|
607
|
+
c.sortVars[ column ].order = ts.getOrder( tmp ) ? [ 1, 1 ] : [ 0, 0 ];
|
|
608
|
+
}
|
|
609
|
+
// add cell to headerList
|
|
610
|
+
c.headerList[ index ] = elem;
|
|
611
|
+
$elem.addClass( ts.css.header + ' ' + c.cssHeader );
|
|
612
|
+
// add to parent in case there are multiple rows
|
|
613
|
+
ts.getClosest( $elem, 'tr' )
|
|
614
|
+
.addClass( ts.css.headerRow + ' ' + c.cssHeaderRow )
|
|
615
|
+
.attr( 'role', 'row' );
|
|
616
|
+
// allow keyboard cursor to focus on element
|
|
617
|
+
if ( c.tabIndex ) {
|
|
618
|
+
$elem.attr( 'tabindex', 0 );
|
|
619
|
+
}
|
|
620
|
+
return elem;
|
|
621
|
+
}) );
|
|
622
|
+
// cache headers per column
|
|
623
|
+
c.$headerIndexed = [];
|
|
624
|
+
for ( indx = 0; indx < c.columns; indx++ ) {
|
|
625
|
+
// colspan in header making a column undefined
|
|
626
|
+
if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {
|
|
627
|
+
c.sortVars[ indx ] = {};
|
|
628
|
+
}
|
|
629
|
+
// Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td
|
|
630
|
+
$temp = c.$headers.filter( '[data-column="' + indx + '"]' );
|
|
631
|
+
// target sortable column cells, unless there are none, then use non-sortable cells
|
|
632
|
+
// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6
|
|
633
|
+
c.$headerIndexed[ indx ] = $temp.length ?
|
|
634
|
+
$temp.not( '.sorter-false' ).length ?
|
|
635
|
+
$temp.not( '.sorter-false' ).filter( ':last' ) :
|
|
636
|
+
$temp.filter( ':last' ) :
|
|
637
|
+
$();
|
|
638
|
+
}
|
|
639
|
+
c.$table.find( c.selectorHeaders ).attr({
|
|
640
|
+
scope: 'col',
|
|
641
|
+
role : 'columnheader'
|
|
642
|
+
});
|
|
643
|
+
// enable/disable sorting
|
|
644
|
+
ts.updateHeader( c );
|
|
645
|
+
if ( ts.debug(c, 'core') ) {
|
|
646
|
+
console.log( 'Built headers:' + ts.benchmark( timer ) );
|
|
647
|
+
console.log( c.$headers );
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
|
|
651
|
+
// Use it to add a set of methods to table.config which will be available for all tables.
|
|
652
|
+
// This should be done before table initialization
|
|
653
|
+
addInstanceMethods : function( methods ) {
|
|
654
|
+
$.extend( ts.instanceMethods, methods );
|
|
655
|
+
},
|
|
656
|
+
|
|
657
|
+
/*
|
|
658
|
+
█████▄ ▄████▄ █████▄ ▄█████ ██████ █████▄ ▄█████
|
|
659
|
+
██▄▄██ ██▄▄██ ██▄▄██ ▀█▄ ██▄▄ ██▄▄██ ▀█▄
|
|
660
|
+
██▀▀▀ ██▀▀██ ██▀██ ▀█▄ ██▀▀ ██▀██ ▀█▄
|
|
661
|
+
██ ██ ██ ██ ██ █████▀ ██████ ██ ██ █████▀
|
|
662
|
+
*/
|
|
663
|
+
setupParsers : function( c, $tbodies ) {
|
|
664
|
+
var rows, list, span, max, colIndex, indx, header, configHeaders,
|
|
665
|
+
noParser, parser, extractor, time, tbody, len,
|
|
666
|
+
table = c.table,
|
|
667
|
+
tbodyIndex = 0,
|
|
668
|
+
debug = ts.debug(c, 'core'),
|
|
669
|
+
debugOutput = {};
|
|
670
|
+
// update table bodies in case we start with an empty table
|
|
671
|
+
c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
|
|
672
|
+
tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;
|
|
673
|
+
len = tbody.length;
|
|
674
|
+
if ( len === 0 ) {
|
|
675
|
+
return debug ? console.warn( 'Warning: *Empty table!* Not building a parser cache' ) : '';
|
|
676
|
+
} else if ( debug ) {
|
|
677
|
+
time = new Date();
|
|
678
|
+
console[ console.group ? 'group' : 'log' ]( 'Detecting parsers for each column' );
|
|
679
|
+
}
|
|
680
|
+
list = {
|
|
681
|
+
extractors: [],
|
|
682
|
+
parsers: []
|
|
683
|
+
};
|
|
684
|
+
while ( tbodyIndex < len ) {
|
|
685
|
+
rows = tbody[ tbodyIndex ].rows;
|
|
686
|
+
if ( rows.length ) {
|
|
687
|
+
colIndex = 0;
|
|
688
|
+
max = c.columns;
|
|
689
|
+
for ( indx = 0; indx < max; indx++ ) {
|
|
690
|
+
header = c.$headerIndexed[ colIndex ];
|
|
691
|
+
if ( header && header.length ) {
|
|
692
|
+
// get column indexed table cell; adding true parameter fixes #1362 but
|
|
693
|
+
// it would break backwards compatibility...
|
|
694
|
+
configHeaders = ts.getColumnData( table, c.headers, colIndex ); // , true );
|
|
244
695
|
// get column parser/extractor
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
696
|
+
extractor = ts.getParserById( ts.getData( header, configHeaders, 'extractor' ) );
|
|
697
|
+
parser = ts.getParserById( ts.getData( header, configHeaders, 'sorter' ) );
|
|
698
|
+
noParser = ts.getData( header, configHeaders, 'parser' ) === 'false';
|
|
248
699
|
// empty cells behaviour - keeping emptyToBottom for backwards compatibility
|
|
249
|
-
c.empties[
|
|
700
|
+
c.empties[colIndex] = (
|
|
701
|
+
ts.getData( header, configHeaders, 'empty' ) ||
|
|
702
|
+
c.emptyTo || ( c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();
|
|
250
703
|
// text strings behaviour in numerical sorts
|
|
251
|
-
c.strings[
|
|
252
|
-
|
|
253
|
-
|
|
704
|
+
c.strings[colIndex] = (
|
|
705
|
+
ts.getData( header, configHeaders, 'string' ) ||
|
|
706
|
+
c.stringTo ||
|
|
707
|
+
'max' ).toLowerCase();
|
|
708
|
+
if ( noParser ) {
|
|
709
|
+
parser = ts.getParserById( 'no-parser' );
|
|
254
710
|
}
|
|
255
|
-
if (!
|
|
711
|
+
if ( !extractor ) {
|
|
256
712
|
// For now, maybe detect someday
|
|
257
|
-
|
|
713
|
+
extractor = false;
|
|
258
714
|
}
|
|
259
|
-
if (!
|
|
260
|
-
|
|
715
|
+
if ( !parser ) {
|
|
716
|
+
parser = ts.detectParserForColumn( c, rows, -1, colIndex );
|
|
261
717
|
}
|
|
262
|
-
if (
|
|
263
|
-
|
|
718
|
+
if ( debug ) {
|
|
719
|
+
debugOutput[ '(' + colIndex + ') ' + header.text() ] = {
|
|
720
|
+
parser : parser.id,
|
|
721
|
+
extractor : extractor ? extractor.id : 'none',
|
|
722
|
+
string : c.strings[ colIndex ],
|
|
723
|
+
empty : c.empties[ colIndex ]
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
list.parsers[ colIndex ] = parser;
|
|
727
|
+
list.extractors[ colIndex ] = extractor;
|
|
728
|
+
span = header[ 0 ].colSpan - 1;
|
|
729
|
+
if ( span > 0 ) {
|
|
730
|
+
colIndex += span;
|
|
731
|
+
max += span;
|
|
732
|
+
while ( span + 1 > 0 ) {
|
|
733
|
+
// set colspan columns to use the same parsers & extractors
|
|
734
|
+
list.parsers[ colIndex - span ] = parser;
|
|
735
|
+
list.extractors[ colIndex - span ] = extractor;
|
|
736
|
+
span--;
|
|
737
|
+
}
|
|
264
738
|
}
|
|
265
|
-
list.parsers[i] = p;
|
|
266
|
-
list.extractors[i] = e;
|
|
267
739
|
}
|
|
740
|
+
colIndex++;
|
|
268
741
|
}
|
|
269
|
-
j += (list.parsers.length) ? len : 1;
|
|
270
742
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
743
|
+
tbodyIndex += ( list.parsers.length ) ? len : 1;
|
|
744
|
+
}
|
|
745
|
+
if ( debug ) {
|
|
746
|
+
if ( !ts.isEmptyObject( debugOutput ) ) {
|
|
747
|
+
console[ console.table ? 'table' : 'log' ]( debugOutput );
|
|
748
|
+
} else {
|
|
749
|
+
console.warn( ' No parsers detected!' );
|
|
750
|
+
}
|
|
751
|
+
console.log( 'Completed detecting parsers' + ts.benchmark( time ) );
|
|
752
|
+
if ( console.groupEnd ) { console.groupEnd(); }
|
|
753
|
+
}
|
|
754
|
+
c.parsers = list.parsers;
|
|
755
|
+
c.extractors = list.extractors;
|
|
756
|
+
},
|
|
757
|
+
|
|
758
|
+
addParser : function( parser ) {
|
|
759
|
+
var indx,
|
|
760
|
+
len = ts.parsers.length,
|
|
761
|
+
add = true;
|
|
762
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
763
|
+
if ( ts.parsers[ indx ].id.toLowerCase() === parser.id.toLowerCase() ) {
|
|
764
|
+
add = false;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if ( add ) {
|
|
768
|
+
ts.parsers[ ts.parsers.length ] = parser;
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
getParserById : function( name ) {
|
|
773
|
+
/*jshint eqeqeq:false */ // eslint-disable-next-line eqeqeq
|
|
774
|
+
if ( name == 'false' ) { return false; }
|
|
775
|
+
var indx,
|
|
776
|
+
len = ts.parsers.length;
|
|
777
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
778
|
+
if ( ts.parsers[ indx ].id.toLowerCase() === ( name.toString() ).toLowerCase() ) {
|
|
779
|
+
return ts.parsers[ indx ];
|
|
274
780
|
}
|
|
275
|
-
c.parsers = list.parsers;
|
|
276
|
-
c.extractors = list.extractors;
|
|
277
781
|
}
|
|
782
|
+
return false;
|
|
783
|
+
},
|
|
278
784
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
785
|
+
detectParserForColumn : function( c, rows, rowIndex, cellIndex ) {
|
|
786
|
+
var cur, $node, row,
|
|
787
|
+
indx = ts.parsers.length,
|
|
788
|
+
node = false,
|
|
789
|
+
nodeValue = '',
|
|
790
|
+
debug = ts.debug(c, 'core'),
|
|
791
|
+
keepLooking = true;
|
|
792
|
+
while ( nodeValue === '' && keepLooking ) {
|
|
793
|
+
rowIndex++;
|
|
794
|
+
row = rows[ rowIndex ];
|
|
795
|
+
// stop looking after 50 empty rows
|
|
796
|
+
if ( row && rowIndex < 50 ) {
|
|
797
|
+
if ( row.className.indexOf( ts.cssIgnoreRow ) < 0 ) {
|
|
798
|
+
node = rows[ rowIndex ].cells[ cellIndex ];
|
|
799
|
+
nodeValue = ts.getElementText( c, node, cellIndex );
|
|
800
|
+
$node = $( node );
|
|
801
|
+
if ( debug ) {
|
|
802
|
+
console.log( 'Checking if value was empty on row ' + rowIndex + ', column: ' +
|
|
803
|
+
cellIndex + ': "' + nodeValue + '"' );
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
keepLooking = false;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
while ( --indx >= 0 ) {
|
|
811
|
+
cur = ts.parsers[ indx ];
|
|
812
|
+
// ignore the default text parser because it will always be true
|
|
813
|
+
if ( cur && cur.id !== 'text' && cur.is && cur.is( nodeValue, c.table, node, $node ) ) {
|
|
814
|
+
return cur;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
// nothing found, return the generic parser (text)
|
|
818
|
+
return ts.getParserById( 'text' );
|
|
819
|
+
},
|
|
820
|
+
|
|
821
|
+
getElementText : function( c, node, cellIndex ) {
|
|
822
|
+
if ( !node ) { return ''; }
|
|
823
|
+
var tmp,
|
|
824
|
+
extract = c.textExtraction || '',
|
|
825
|
+
// node could be a jquery object
|
|
826
|
+
// http://jsperf.com/jquery-vs-instanceof-jquery/2
|
|
827
|
+
$node = node.jquery ? node : $( node );
|
|
828
|
+
if ( typeof extract === 'string' ) {
|
|
829
|
+
// check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!
|
|
830
|
+
// http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/
|
|
831
|
+
if ( extract === 'basic' && typeof ( tmp = $node.attr( c.textAttribute ) ) !== 'undefined' ) {
|
|
832
|
+
return $.trim( tmp );
|
|
833
|
+
}
|
|
834
|
+
return $.trim( node.textContent || $node.text() );
|
|
835
|
+
} else {
|
|
836
|
+
if ( typeof extract === 'function' ) {
|
|
837
|
+
return $.trim( extract( $node[ 0 ], c.table, cellIndex ) );
|
|
838
|
+
} else if ( typeof ( tmp = ts.getColumnData( c.table, extract, cellIndex ) ) === 'function' ) {
|
|
839
|
+
return $.trim( tmp( $node[ 0 ], c.table, cellIndex ) );
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
// fallback
|
|
843
|
+
return $.trim( $node[ 0 ].textContent || $node.text() );
|
|
844
|
+
},
|
|
845
|
+
|
|
846
|
+
// centralized function to extract/parse cell contents
|
|
847
|
+
getParsedText : function( c, cell, colIndex, txt ) {
|
|
848
|
+
if ( typeof txt === 'undefined' ) {
|
|
849
|
+
txt = ts.getElementText( c, cell, colIndex );
|
|
850
|
+
}
|
|
851
|
+
// if no parser, make sure to return the txt
|
|
852
|
+
var val = '' + txt,
|
|
853
|
+
parser = c.parsers[ colIndex ],
|
|
854
|
+
extractor = c.extractors[ colIndex ];
|
|
855
|
+
if ( parser ) {
|
|
856
|
+
// do extract before parsing, if there is one
|
|
857
|
+
if ( extractor && typeof extractor.format === 'function' ) {
|
|
858
|
+
txt = extractor.format( txt, c.table, cell, colIndex );
|
|
859
|
+
}
|
|
860
|
+
// allow parsing if the string is empty, previously parsing would change it to zero,
|
|
861
|
+
// in case the parser needs to extract data from the table cell attributes
|
|
862
|
+
val = parser.id === 'no-parser' ? '' :
|
|
863
|
+
// make sure txt is a string (extractor may have converted it)
|
|
864
|
+
parser.format( '' + txt, c.table, cell, colIndex );
|
|
865
|
+
if ( c.ignoreCase && typeof val === 'string' ) {
|
|
866
|
+
val = val.toLowerCase();
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
return val;
|
|
870
|
+
},
|
|
871
|
+
|
|
872
|
+
/*
|
|
873
|
+
▄████▄ ▄████▄ ▄████▄ ██ ██ ██████
|
|
874
|
+
██ ▀▀ ██▄▄██ ██ ▀▀ ██▄▄██ ██▄▄
|
|
875
|
+
██ ▄▄ ██▀▀██ ██ ▄▄ ██▀▀██ ██▀▀
|
|
876
|
+
▀████▀ ██ ██ ▀████▀ ██ ██ ██████
|
|
877
|
+
*/
|
|
878
|
+
buildCache : function( c, callback, $tbodies ) {
|
|
879
|
+
var cache, val, txt, rowIndex, colIndex, tbodyIndex, $tbody, $row,
|
|
880
|
+
cols, $cells, cell, cacheTime, totalRows, rowData, prevRowData,
|
|
881
|
+
colMax, span, cacheIndex, hasParser, max, len, index,
|
|
882
|
+
table = c.table,
|
|
883
|
+
parsers = c.parsers,
|
|
884
|
+
debug = ts.debug(c, 'core');
|
|
885
|
+
// update tbody variable
|
|
886
|
+
c.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );
|
|
887
|
+
$tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies,
|
|
287
888
|
c.cache = {};
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
889
|
+
c.totalRows = 0;
|
|
890
|
+
// if no parsers found, return - it's an empty table.
|
|
891
|
+
if ( !parsers ) {
|
|
892
|
+
return debug ? console.warn( 'Warning: *Empty table!* Not building a cache' ) : '';
|
|
893
|
+
}
|
|
894
|
+
if ( debug ) {
|
|
895
|
+
cacheTime = new Date();
|
|
896
|
+
}
|
|
897
|
+
// processing icon
|
|
898
|
+
if ( c.showProcessing ) {
|
|
899
|
+
ts.isProcessing( table, true );
|
|
900
|
+
}
|
|
901
|
+
for ( tbodyIndex = 0; tbodyIndex < $tbody.length; tbodyIndex++ ) {
|
|
902
|
+
colMax = []; // column max value per tbody
|
|
903
|
+
cache = c.cache[ tbodyIndex ] = {
|
|
904
|
+
normalized: [] // array of normalized row data; last entry contains 'rowData' above
|
|
905
|
+
// colMax: # // added at the end
|
|
906
|
+
};
|
|
306
907
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
908
|
+
totalRows = ( $tbody[ tbodyIndex ] && $tbody[ tbodyIndex ].rows.length ) || 0;
|
|
909
|
+
for ( rowIndex = 0; rowIndex < totalRows; ++rowIndex ) {
|
|
910
|
+
rowData = {
|
|
911
|
+
// order: original row order #
|
|
912
|
+
// $row : jQuery Object[]
|
|
913
|
+
child: [], // child row text (filter widget)
|
|
914
|
+
raw: [] // original row text
|
|
915
|
+
};
|
|
916
|
+
/** Add the table data to main data array */
|
|
917
|
+
$row = $( $tbody[ tbodyIndex ].rows[ rowIndex ] );
|
|
918
|
+
cols = [];
|
|
919
|
+
// ignore "remove-me" rows
|
|
920
|
+
if ( $row.hasClass( c.selectorRemove.slice(1) ) ) {
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
// if this is a child row, add it to the last row's children and continue to the next row
|
|
924
|
+
// ignore child row class, if it is the first row
|
|
925
|
+
if ( $row.hasClass( c.cssChildRow ) && rowIndex !== 0 ) {
|
|
926
|
+
len = cache.normalized.length - 1;
|
|
927
|
+
prevRowData = cache.normalized[ len ][ c.columns ];
|
|
928
|
+
prevRowData.$row = prevRowData.$row.add( $row );
|
|
929
|
+
// add 'hasChild' class name to parent row
|
|
930
|
+
if ( !$row.prev().hasClass( c.cssChildRow ) ) {
|
|
931
|
+
$row.prev().addClass( ts.css.cssHasChild );
|
|
932
|
+
}
|
|
933
|
+
// save child row content (un-parsed!)
|
|
934
|
+
$cells = $row.children( 'th, td' );
|
|
935
|
+
len = prevRowData.child.length;
|
|
936
|
+
prevRowData.child[ len ] = [];
|
|
937
|
+
// child row content does not account for colspans/rowspans; so indexing may be off
|
|
938
|
+
cacheIndex = 0;
|
|
939
|
+
max = c.columns;
|
|
940
|
+
for ( colIndex = 0; colIndex < max; colIndex++ ) {
|
|
941
|
+
cell = $cells[ colIndex ];
|
|
942
|
+
if ( cell ) {
|
|
943
|
+
prevRowData.child[ len ][ colIndex ] = ts.getParsedText( c, cell, colIndex );
|
|
944
|
+
span = $cells[ colIndex ].colSpan - 1;
|
|
945
|
+
if ( span > 0 ) {
|
|
946
|
+
cacheIndex += span;
|
|
947
|
+
max += span;
|
|
328
948
|
}
|
|
329
|
-
// save child row content (un-parsed!)
|
|
330
|
-
rowData.child[t] = $.trim( $row[0].textContent || $row[0].innerText || $row.text() || "" );
|
|
331
|
-
// go to the next for loop
|
|
332
|
-
continue;
|
|
333
949
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
950
|
+
cacheIndex++;
|
|
951
|
+
}
|
|
952
|
+
// go to the next for loop
|
|
953
|
+
continue;
|
|
954
|
+
}
|
|
955
|
+
rowData.$row = $row;
|
|
956
|
+
rowData.order = rowIndex; // add original row position to rowCache
|
|
957
|
+
cacheIndex = 0;
|
|
958
|
+
max = c.columns;
|
|
959
|
+
for ( colIndex = 0; colIndex < max; ++colIndex ) {
|
|
960
|
+
cell = $row[ 0 ].cells[ colIndex ];
|
|
961
|
+
if ( cell && cacheIndex < c.columns ) {
|
|
962
|
+
hasParser = typeof parsers[ cacheIndex ] !== 'undefined';
|
|
963
|
+
if ( !hasParser && debug ) {
|
|
964
|
+
console.warn( 'No parser found for row: ' + rowIndex + ', column: ' + colIndex +
|
|
965
|
+
'; cell containing: "' + $(cell).text() + '"; does it have a header?' );
|
|
966
|
+
}
|
|
967
|
+
val = ts.getElementText( c, cell, cacheIndex );
|
|
968
|
+
rowData.raw[ cacheIndex ] = val; // save original row text
|
|
969
|
+
// save raw column text even if there is no parser set
|
|
970
|
+
txt = ts.getParsedText( c, cell, cacheIndex, val );
|
|
971
|
+
cols[ cacheIndex ] = txt;
|
|
972
|
+
if ( hasParser && ( parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {
|
|
973
|
+
// determine column max value (ignore sign)
|
|
974
|
+
colMax[ cacheIndex ] = Math.max( Math.abs( txt ) || 0, colMax[ cacheIndex ] || 0 );
|
|
975
|
+
}
|
|
976
|
+
// allow colSpan in tbody
|
|
977
|
+
span = cell.colSpan - 1;
|
|
978
|
+
if ( span > 0 ) {
|
|
979
|
+
index = 0;
|
|
980
|
+
while ( index <= span ) {
|
|
981
|
+
// duplicate text (or not) to spanned columns
|
|
982
|
+
// instead of setting duplicate span to empty string, use textExtraction to try to get a value
|
|
983
|
+
// see http://stackoverflow.com/q/36449711/145346
|
|
984
|
+
txt = c.duplicateSpan || index === 0 ?
|
|
985
|
+
txt :
|
|
986
|
+
typeof c.textExtraction !== 'string' ?
|
|
987
|
+
ts.getElementText( c, cell, cacheIndex + index ) || '' :
|
|
988
|
+
'';
|
|
989
|
+
rowData.raw[ cacheIndex + index ] = txt;
|
|
990
|
+
cols[ cacheIndex + index ] = txt;
|
|
991
|
+
index++;
|
|
357
992
|
}
|
|
993
|
+
cacheIndex += span;
|
|
994
|
+
max += span;
|
|
358
995
|
}
|
|
359
|
-
// ensure rowData is always in the same location (after the last column)
|
|
360
|
-
cols[c.columns] = rowData;
|
|
361
|
-
cc.normalized.push(cols);
|
|
362
996
|
}
|
|
363
|
-
|
|
364
|
-
// total up rows, not including child rows
|
|
365
|
-
c.totalRows += cc.normalized.length;
|
|
997
|
+
cacheIndex++;
|
|
366
998
|
}
|
|
999
|
+
// ensure rowData is always in the same location (after the last column)
|
|
1000
|
+
cols[ c.columns ] = rowData;
|
|
1001
|
+
cache.normalized[ cache.normalized.length ] = cols;
|
|
367
1002
|
}
|
|
368
|
-
|
|
369
|
-
|
|
1003
|
+
cache.colMax = colMax;
|
|
1004
|
+
// total up rows, not including child rows
|
|
1005
|
+
c.totalRows += cache.normalized.length;
|
|
1006
|
+
|
|
1007
|
+
}
|
|
1008
|
+
if ( c.showProcessing ) {
|
|
1009
|
+
ts.isProcessing( table ); // remove processing icon
|
|
1010
|
+
}
|
|
1011
|
+
if ( debug ) {
|
|
1012
|
+
len = Math.min( 5, c.cache[ 0 ].normalized.length );
|
|
1013
|
+
console[ console.group ? 'group' : 'log' ]( 'Building cache for ' + c.totalRows +
|
|
1014
|
+
' rows (showing ' + len + ' rows in log) and ' + c.columns + ' columns' +
|
|
1015
|
+
ts.benchmark( cacheTime ) );
|
|
1016
|
+
val = {};
|
|
1017
|
+
for ( colIndex = 0; colIndex < c.columns; colIndex++ ) {
|
|
1018
|
+
for ( cacheIndex = 0; cacheIndex < len; cacheIndex++ ) {
|
|
1019
|
+
if ( !val[ 'row: ' + cacheIndex ] ) {
|
|
1020
|
+
val[ 'row: ' + cacheIndex ] = {};
|
|
1021
|
+
}
|
|
1022
|
+
val[ 'row: ' + cacheIndex ][ c.$headerIndexed[ colIndex ].text() ] =
|
|
1023
|
+
c.cache[ 0 ].normalized[ cacheIndex ][ colIndex ];
|
|
1024
|
+
}
|
|
370
1025
|
}
|
|
371
|
-
|
|
372
|
-
|
|
1026
|
+
console[ console.table ? 'table' : 'log' ]( val );
|
|
1027
|
+
if ( console.groupEnd ) { console.groupEnd(); }
|
|
1028
|
+
}
|
|
1029
|
+
if ( $.isFunction( callback ) ) {
|
|
1030
|
+
callback( table );
|
|
1031
|
+
}
|
|
1032
|
+
},
|
|
1033
|
+
|
|
1034
|
+
getColumnText : function( table, column, callback, rowFilter ) {
|
|
1035
|
+
table = $( table )[0];
|
|
1036
|
+
var tbodyIndex, rowIndex, cache, row, tbodyLen, rowLen, raw, parsed, $cell, result,
|
|
1037
|
+
hasCallback = typeof callback === 'function',
|
|
1038
|
+
allColumns = column === 'all',
|
|
1039
|
+
data = { raw : [], parsed: [], $cell: [] },
|
|
1040
|
+
c = table.config;
|
|
1041
|
+
if ( ts.isEmptyObject( c ) ) {
|
|
1042
|
+
if ( ts.debug(c, 'core') ) {
|
|
1043
|
+
console.warn( 'No cache found - aborting getColumnText function!' );
|
|
1044
|
+
}
|
|
1045
|
+
} else {
|
|
1046
|
+
tbodyLen = c.$tbodies.length;
|
|
1047
|
+
for ( tbodyIndex = 0; tbodyIndex < tbodyLen; tbodyIndex++ ) {
|
|
1048
|
+
cache = c.cache[ tbodyIndex ].normalized;
|
|
1049
|
+
rowLen = cache.length;
|
|
1050
|
+
for ( rowIndex = 0; rowIndex < rowLen; rowIndex++ ) {
|
|
1051
|
+
row = cache[ rowIndex ];
|
|
1052
|
+
if ( rowFilter && !row[ c.columns ].$row.is( rowFilter ) ) {
|
|
1053
|
+
continue;
|
|
1054
|
+
}
|
|
1055
|
+
result = true;
|
|
1056
|
+
parsed = ( allColumns ) ? row.slice( 0, c.columns ) : row[ column ];
|
|
1057
|
+
row = row[ c.columns ];
|
|
1058
|
+
raw = ( allColumns ) ? row.raw : row.raw[ column ];
|
|
1059
|
+
$cell = ( allColumns ) ? row.$row.children() : row.$row.children().eq( column );
|
|
1060
|
+
if ( hasCallback ) {
|
|
1061
|
+
result = callback({
|
|
1062
|
+
tbodyIndex : tbodyIndex,
|
|
1063
|
+
rowIndex : rowIndex,
|
|
1064
|
+
parsed : parsed,
|
|
1065
|
+
raw : raw,
|
|
1066
|
+
$row : row.$row,
|
|
1067
|
+
$cell : $cell
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
if ( result !== false ) {
|
|
1071
|
+
data.parsed[ data.parsed.length ] = parsed;
|
|
1072
|
+
data.raw[ data.raw.length ] = raw;
|
|
1073
|
+
data.$cell[ data.$cell.length ] = $cell;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
373
1076
|
}
|
|
1077
|
+
// return everything
|
|
1078
|
+
return data;
|
|
374
1079
|
}
|
|
1080
|
+
},
|
|
375
1081
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
1082
|
+
/*
|
|
1083
|
+
██ ██ █████▄ █████▄ ▄████▄ ██████ ██████
|
|
1084
|
+
██ ██ ██▄▄██ ██ ██ ██▄▄██ ██ ██▄▄
|
|
1085
|
+
██ ██ ██▀▀▀ ██ ██ ██▀▀██ ██ ██▀▀
|
|
1086
|
+
▀████▀ ██ █████▀ ██ ██ ██ ██████
|
|
1087
|
+
*/
|
|
1088
|
+
setHeadersCss : function( c ) {
|
|
1089
|
+
var indx, column,
|
|
1090
|
+
list = c.sortList,
|
|
1091
|
+
len = list.length,
|
|
1092
|
+
none = ts.css.sortNone + ' ' + c.cssNone,
|
|
1093
|
+
css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
|
|
1094
|
+
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
|
|
1095
|
+
aria = [ 'ascending', 'descending' ],
|
|
1096
|
+
updateColumnSort = function($el, index) {
|
|
1097
|
+
$el
|
|
1098
|
+
.removeClass( none )
|
|
1099
|
+
.addClass( css[ index ] )
|
|
1100
|
+
.attr( 'aria-sort', aria[ index ] )
|
|
1101
|
+
.find( '.' + ts.css.icon )
|
|
1102
|
+
.removeClass( cssIcon[ 2 ] )
|
|
1103
|
+
.addClass( cssIcon[ index ] );
|
|
1104
|
+
},
|
|
1105
|
+
// find the footer
|
|
1106
|
+
$extras = c.$table
|
|
1107
|
+
.find( 'tfoot tr' )
|
|
1108
|
+
.children( 'td, th' )
|
|
1109
|
+
.add( $( c.namespace + '_extra_headers' ) )
|
|
1110
|
+
.removeClass( css.join( ' ' ) ),
|
|
1111
|
+
// remove all header information
|
|
1112
|
+
$sorted = c.$headers
|
|
1113
|
+
.add( $( 'thead ' + c.namespace + '_extra_headers' ) )
|
|
1114
|
+
.removeClass( css.join( ' ' ) )
|
|
1115
|
+
.addClass( none )
|
|
1116
|
+
.attr( 'aria-sort', 'none' )
|
|
1117
|
+
.find( '.' + ts.css.icon )
|
|
1118
|
+
.removeClass( cssIcon.join( ' ' ) )
|
|
1119
|
+
.end();
|
|
1120
|
+
// add css none to all sortable headers
|
|
1121
|
+
$sorted
|
|
1122
|
+
.not( '.sorter-false' )
|
|
1123
|
+
.find( '.' + ts.css.icon )
|
|
1124
|
+
.addClass( cssIcon[ 2 ] );
|
|
1125
|
+
// add disabled css icon class
|
|
1126
|
+
if ( c.cssIconDisabled ) {
|
|
1127
|
+
$sorted
|
|
1128
|
+
.filter( '.sorter-false' )
|
|
1129
|
+
.find( '.' + ts.css.icon )
|
|
1130
|
+
.addClass( c.cssIconDisabled );
|
|
1131
|
+
}
|
|
1132
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1133
|
+
// direction = 2 means reset!
|
|
1134
|
+
if ( list[ indx ][ 1 ] !== 2 ) {
|
|
1135
|
+
// multicolumn sorting updating - see #1005
|
|
1136
|
+
// .not(function() {}) needs jQuery 1.4
|
|
1137
|
+
// filter(function(i, el) {}) <- el is undefined in jQuery v1.2.6
|
|
1138
|
+
$sorted = c.$headers.filter( function( i ) {
|
|
1139
|
+
// only include headers that are in the sortList (this includes colspans)
|
|
1140
|
+
var include = true,
|
|
1141
|
+
$el = c.$headers.eq( i ),
|
|
1142
|
+
col = parseInt( $el.attr( 'data-column' ), 10 ),
|
|
1143
|
+
end = col + ts.getClosest( $el, 'th, td' )[0].colSpan;
|
|
1144
|
+
for ( ; col < end; col++ ) {
|
|
1145
|
+
include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;
|
|
1146
|
+
}
|
|
1147
|
+
return include;
|
|
1148
|
+
});
|
|
1149
|
+
|
|
1150
|
+
// choose the :last in case there are nested columns
|
|
1151
|
+
$sorted = $sorted
|
|
1152
|
+
.not( '.sorter-false' )
|
|
1153
|
+
.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' + ( len === 1 ? ':last' : '' ) );
|
|
1154
|
+
if ( $sorted.length ) {
|
|
1155
|
+
for ( column = 0; column < $sorted.length; column++ ) {
|
|
1156
|
+
if ( !$sorted[ column ].sortDisabled ) {
|
|
1157
|
+
updateColumnSort( $sorted.eq( column ), list[ indx ][ 1 ] );
|
|
406
1158
|
}
|
|
407
1159
|
}
|
|
408
|
-
|
|
409
|
-
|
|
1160
|
+
}
|
|
1161
|
+
// add sorted class to footer & extra headers, if they exist
|
|
1162
|
+
if ( $extras.length ) {
|
|
1163
|
+
updateColumnSort( $extras.filter( '[data-column="' + list[ indx ][ 0 ] + '"]' ), list[ indx ][ 1 ] );
|
|
410
1164
|
}
|
|
411
1165
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
1166
|
+
}
|
|
1167
|
+
// add verbose aria labels
|
|
1168
|
+
len = c.$headers.length;
|
|
1169
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1170
|
+
ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
|
|
1174
|
+
getClosest : function( $el, selector ) {
|
|
1175
|
+
// jQuery v1.2.6 doesn't have closest()
|
|
1176
|
+
if ( $.fn.closest ) {
|
|
1177
|
+
return $el.closest( selector );
|
|
1178
|
+
}
|
|
1179
|
+
return $el.is( selector ) ?
|
|
1180
|
+
$el :
|
|
1181
|
+
$el.parents( selector ).filter( ':first' );
|
|
1182
|
+
},
|
|
1183
|
+
|
|
1184
|
+
// nextSort (optional), lets you disable next sort text
|
|
1185
|
+
setColumnAriaLabel : function( c, $header, nextSort ) {
|
|
1186
|
+
if ( $header.length ) {
|
|
1187
|
+
var column = parseInt( $header.attr( 'data-column' ), 10 ),
|
|
1188
|
+
vars = c.sortVars[ column ],
|
|
1189
|
+
tmp = $header.hasClass( ts.css.sortAsc ) ?
|
|
1190
|
+
'sortAsc' :
|
|
1191
|
+
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
|
|
1192
|
+
txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
|
|
1193
|
+
if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
|
|
1194
|
+
txt += ts.language.sortDisabled;
|
|
1195
|
+
} else {
|
|
1196
|
+
tmp = ( vars.count + 1 ) % vars.order.length;
|
|
1197
|
+
nextSort = vars.order[ tmp ];
|
|
1198
|
+
// if nextSort
|
|
1199
|
+
txt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
|
|
1200
|
+
}
|
|
1201
|
+
$header.attr( 'aria-label', txt );
|
|
1202
|
+
if (vars.sortedBy) {
|
|
1203
|
+
$header.attr( 'data-sortedBy', vars.sortedBy );
|
|
1204
|
+
} else {
|
|
1205
|
+
$header.removeAttr('data-sortedBy');
|
|
422
1206
|
}
|
|
423
1207
|
}
|
|
1208
|
+
},
|
|
424
1209
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
1210
|
+
updateHeader : function( c ) {
|
|
1211
|
+
var index, isDisabled, $header, col,
|
|
1212
|
+
table = c.table,
|
|
1213
|
+
len = c.$headers.length;
|
|
1214
|
+
for ( index = 0; index < len; index++ ) {
|
|
1215
|
+
$header = c.$headers.eq( index );
|
|
1216
|
+
col = ts.getColumnData( table, c.headers, index, true );
|
|
1217
|
+
// add 'sorter-false' class if 'parser-false' is set
|
|
1218
|
+
isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
|
|
1219
|
+
ts.setColumnSort( c, $header, isDisabled );
|
|
428
1220
|
}
|
|
1221
|
+
},
|
|
429
1222
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
1223
|
+
setColumnSort : function( c, $header, isDisabled ) {
|
|
1224
|
+
var id = c.table.id;
|
|
1225
|
+
$header[ 0 ].sortDisabled = isDisabled;
|
|
1226
|
+
$header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )
|
|
1227
|
+
.attr( 'aria-disabled', '' + isDisabled );
|
|
1228
|
+
// disable tab index on disabled cells
|
|
1229
|
+
if ( c.tabIndex ) {
|
|
1230
|
+
if ( isDisabled ) {
|
|
1231
|
+
$header.removeAttr( 'tabindex' );
|
|
1232
|
+
} else {
|
|
1233
|
+
$header.attr( 'tabindex', '0' );
|
|
438
1234
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
$
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
1235
|
+
}
|
|
1236
|
+
// aria-controls - requires table ID
|
|
1237
|
+
if ( id ) {
|
|
1238
|
+
if ( isDisabled ) {
|
|
1239
|
+
$header.removeAttr( 'aria-controls' );
|
|
1240
|
+
} else {
|
|
1241
|
+
$header.attr( 'aria-controls', id );
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
|
|
1246
|
+
updateHeaderSortCount : function( c, list ) {
|
|
1247
|
+
var col, dir, group, indx, primary, temp, val, order,
|
|
1248
|
+
sortList = list || c.sortList,
|
|
1249
|
+
len = sortList.length;
|
|
1250
|
+
c.sortList = [];
|
|
1251
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1252
|
+
val = sortList[ indx ];
|
|
1253
|
+
// ensure all sortList values are numeric - fixes #127
|
|
1254
|
+
col = parseInt( val[ 0 ], 10 );
|
|
1255
|
+
// prevents error if sorton array is wrong
|
|
1256
|
+
if ( col < c.columns ) {
|
|
1257
|
+
|
|
1258
|
+
// set order if not already defined - due to colspan header without associated header cell
|
|
1259
|
+
// adding this check prevents a javascript error
|
|
1260
|
+
if ( !c.sortVars[ col ].order ) {
|
|
1261
|
+
if ( ts.getOrder( c.sortInitialOrder ) ) {
|
|
1262
|
+
order = c.sortReset ? [ 1, 0, 2 ] : [ 1, 0 ];
|
|
1263
|
+
} else {
|
|
1264
|
+
order = c.sortReset ? [ 0, 1, 2 ] : [ 0, 1 ];
|
|
1265
|
+
}
|
|
1266
|
+
c.sortVars[ col ].order = order;
|
|
1267
|
+
c.sortVars[ col ].count = 0;
|
|
455
1268
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
1269
|
+
|
|
1270
|
+
order = c.sortVars[ col ].order;
|
|
1271
|
+
dir = ( '' + val[ 1 ] ).match( /^(1|d|s|o|n)/ );
|
|
1272
|
+
dir = dir ? dir[ 0 ] : '';
|
|
1273
|
+
// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
|
|
1274
|
+
switch ( dir ) {
|
|
1275
|
+
case '1' : case 'd' : // descending
|
|
1276
|
+
dir = 1;
|
|
1277
|
+
break;
|
|
1278
|
+
case 's' : // same direction (as primary column)
|
|
1279
|
+
// if primary sort is set to 's', make it ascending
|
|
1280
|
+
dir = primary || 0;
|
|
1281
|
+
break;
|
|
1282
|
+
case 'o' :
|
|
1283
|
+
temp = order[ ( primary || 0 ) % order.length ];
|
|
1284
|
+
// opposite of primary column; but resets if primary resets
|
|
1285
|
+
dir = temp === 0 ? 1 : temp === 1 ? 0 : 2;
|
|
1286
|
+
break;
|
|
1287
|
+
case 'n' :
|
|
1288
|
+
dir = order[ ( ++c.sortVars[ col ].count ) % order.length ];
|
|
1289
|
+
break;
|
|
1290
|
+
default : // ascending
|
|
1291
|
+
dir = 0;
|
|
1292
|
+
break;
|
|
466
1293
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
c.
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
1294
|
+
primary = indx === 0 ? dir : primary;
|
|
1295
|
+
group = [ col, parseInt( dir, 10 ) || 0 ];
|
|
1296
|
+
c.sortList[ c.sortList.length ] = group;
|
|
1297
|
+
dir = $.inArray( group[ 1 ], order ); // fixes issue #167
|
|
1298
|
+
c.sortVars[ col ].count = dir >= 0 ? dir : group[ 1 ] % order.length;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
},
|
|
1302
|
+
|
|
1303
|
+
updateAll : function( c, resort, callback ) {
|
|
1304
|
+
var table = c.table;
|
|
1305
|
+
table.isUpdating = true;
|
|
1306
|
+
ts.refreshWidgets( table, true, true );
|
|
1307
|
+
ts.buildHeaders( c );
|
|
1308
|
+
ts.bindEvents( table, c.$headers, true );
|
|
1309
|
+
ts.bindMethods( c );
|
|
1310
|
+
ts.commonUpdate( c, resort, callback );
|
|
1311
|
+
},
|
|
1312
|
+
|
|
1313
|
+
update : function( c, resort, callback ) {
|
|
1314
|
+
var table = c.table;
|
|
1315
|
+
table.isUpdating = true;
|
|
1316
|
+
// update sorting (if enabled/disabled)
|
|
1317
|
+
ts.updateHeader( c );
|
|
1318
|
+
ts.commonUpdate( c, resort, callback );
|
|
1319
|
+
},
|
|
1320
|
+
|
|
1321
|
+
// simple header update - see #989
|
|
1322
|
+
updateHeaders : function( c, callback ) {
|
|
1323
|
+
c.table.isUpdating = true;
|
|
1324
|
+
ts.buildHeaders( c );
|
|
1325
|
+
ts.bindEvents( c.table, c.$headers, true );
|
|
1326
|
+
ts.resortComplete( c, callback );
|
|
1327
|
+
},
|
|
1328
|
+
|
|
1329
|
+
updateCell : function( c, cell, resort, callback ) {
|
|
1330
|
+
// updateCell for child rows is a mess - we'll ignore them for now
|
|
1331
|
+
// eventually I'll break out the "update" row cache code to make everything consistent
|
|
1332
|
+
if ( $( cell ).closest( 'tr' ).hasClass( c.cssChildRow ) ) {
|
|
1333
|
+
console.warn('Tablesorter Warning! "updateCell" for child row content has been disabled, use "update" instead');
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
if ( ts.isEmptyObject( c.cache ) ) {
|
|
1337
|
+
// empty table, do an update instead - fixes #1099
|
|
1338
|
+
ts.updateHeader( c );
|
|
1339
|
+
ts.commonUpdate( c, resort, callback );
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
c.table.isUpdating = true;
|
|
1343
|
+
c.$table.find( c.selectorRemove ).remove();
|
|
1344
|
+
// get position from the dom
|
|
1345
|
+
var tmp, indx, row, icell, cache, len,
|
|
1346
|
+
$tbodies = c.$tbodies,
|
|
1347
|
+
$cell = $( cell ),
|
|
1348
|
+
// update cache - format: function( s, table, cell, cellIndex )
|
|
1349
|
+
// no closest in jQuery v1.2.6
|
|
1350
|
+
tbodyIndex = $tbodies.index( ts.getClosest( $cell, 'tbody' ) ),
|
|
1351
|
+
tbcache = c.cache[ tbodyIndex ],
|
|
1352
|
+
$row = ts.getClosest( $cell, 'tr' );
|
|
1353
|
+
cell = $cell[ 0 ]; // in case cell is a jQuery object
|
|
1354
|
+
// tbody may not exist if update is initialized while tbody is removed for processing
|
|
1355
|
+
if ( $tbodies.length && tbodyIndex >= 0 ) {
|
|
1356
|
+
row = $tbodies.eq( tbodyIndex ).find( 'tr' ).not( '.' + c.cssChildRow ).index( $row );
|
|
1357
|
+
cache = tbcache.normalized[ row ];
|
|
1358
|
+
len = $row[ 0 ].cells.length;
|
|
1359
|
+
if ( len !== c.columns ) {
|
|
1360
|
+
// colspan in here somewhere!
|
|
1361
|
+
icell = 0;
|
|
1362
|
+
tmp = false;
|
|
1363
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1364
|
+
if ( !tmp && $row[ 0 ].cells[ indx ] !== cell ) {
|
|
1365
|
+
icell += $row[ 0 ].cells[ indx ].colSpan;
|
|
511
1366
|
} else {
|
|
512
|
-
|
|
1367
|
+
tmp = true;
|
|
513
1368
|
}
|
|
514
1369
|
}
|
|
515
|
-
}
|
|
1370
|
+
} else {
|
|
1371
|
+
icell = $cell.index();
|
|
1372
|
+
}
|
|
1373
|
+
tmp = ts.getElementText( c, cell, icell ); // raw
|
|
1374
|
+
cache[ c.columns ].raw[ icell ] = tmp;
|
|
1375
|
+
tmp = ts.getParsedText( c, cell, icell, tmp );
|
|
1376
|
+
cache[ icell ] = tmp; // parsed
|
|
1377
|
+
if ( ( c.parsers[ icell ].type || '' ).toLowerCase() === 'numeric' ) {
|
|
1378
|
+
// update column max value (ignore sign)
|
|
1379
|
+
tbcache.colMax[ icell ] = Math.max( Math.abs( tmp ) || 0, tbcache.colMax[ icell ] || 0 );
|
|
1380
|
+
}
|
|
1381
|
+
tmp = resort !== 'undefined' ? resort : c.resort;
|
|
1382
|
+
if ( tmp !== false ) {
|
|
1383
|
+
// widgets will be reapplied
|
|
1384
|
+
ts.checkResort( c, tmp, callback );
|
|
1385
|
+
} else {
|
|
1386
|
+
// don't reapply widgets is resort is false, just in case it causes
|
|
1387
|
+
// problems with element focus
|
|
1388
|
+
ts.resortComplete( c, callback );
|
|
1389
|
+
}
|
|
1390
|
+
} else {
|
|
1391
|
+
if ( ts.debug(c, 'core') ) {
|
|
1392
|
+
console.error( 'updateCell aborted, tbody missing or not within the indicated table' );
|
|
1393
|
+
}
|
|
1394
|
+
c.table.isUpdating = false;
|
|
516
1395
|
}
|
|
1396
|
+
},
|
|
517
1397
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
1398
|
+
addRows : function( c, $row, resort, callback ) {
|
|
1399
|
+
var txt, val, tbodyIndex, rowIndex, rows, cellIndex, len, order,
|
|
1400
|
+
cacheIndex, rowData, cells, cell, span,
|
|
1401
|
+
// allow passing a row string if only one non-info tbody exists in the table
|
|
1402
|
+
valid = typeof $row === 'string' && c.$tbodies.length === 1 && /<tr/.test( $row || '' ),
|
|
1403
|
+
table = c.table;
|
|
1404
|
+
if ( valid ) {
|
|
1405
|
+
$row = $( $row );
|
|
1406
|
+
c.$tbodies.append( $row );
|
|
1407
|
+
} else if (
|
|
1408
|
+
!$row ||
|
|
1409
|
+
// row is a jQuery object?
|
|
1410
|
+
!( $row instanceof $ ) ||
|
|
1411
|
+
// row contained in the table?
|
|
1412
|
+
( ts.getClosest( $row, 'table' )[ 0 ] !== c.table )
|
|
1413
|
+
) {
|
|
1414
|
+
if ( ts.debug(c, 'core') ) {
|
|
1415
|
+
console.error( 'addRows method requires (1) a jQuery selector reference to rows that have already ' +
|
|
1416
|
+
'been added to the table, or (2) row HTML string to be added to a table with only one tbody' );
|
|
1417
|
+
}
|
|
1418
|
+
return false;
|
|
1419
|
+
}
|
|
1420
|
+
table.isUpdating = true;
|
|
1421
|
+
if ( ts.isEmptyObject( c.cache ) ) {
|
|
1422
|
+
// empty table, do an update instead - fixes #450
|
|
1423
|
+
ts.updateHeader( c );
|
|
1424
|
+
ts.commonUpdate( c, resort, callback );
|
|
1425
|
+
} else {
|
|
1426
|
+
rows = $row.filter( 'tr' ).attr( 'role', 'row' ).length;
|
|
1427
|
+
tbodyIndex = c.$tbodies.index( $row.parents( 'tbody' ).filter( ':first' ) );
|
|
1428
|
+
// fixes adding rows to an empty table - see issue #179
|
|
1429
|
+
if ( !( c.parsers && c.parsers.length ) ) {
|
|
1430
|
+
ts.setupParsers( c );
|
|
1431
|
+
}
|
|
1432
|
+
// add each row
|
|
1433
|
+
for ( rowIndex = 0; rowIndex < rows; rowIndex++ ) {
|
|
1434
|
+
cacheIndex = 0;
|
|
1435
|
+
len = $row[ rowIndex ].cells.length;
|
|
1436
|
+
order = c.cache[ tbodyIndex ].normalized.length;
|
|
1437
|
+
cells = [];
|
|
1438
|
+
rowData = {
|
|
1439
|
+
child : [],
|
|
1440
|
+
raw : [],
|
|
1441
|
+
$row : $row.eq( rowIndex ),
|
|
1442
|
+
order : order
|
|
1443
|
+
};
|
|
1444
|
+
// add each cell
|
|
1445
|
+
for ( cellIndex = 0; cellIndex < len; cellIndex++ ) {
|
|
1446
|
+
cell = $row[ rowIndex ].cells[ cellIndex ];
|
|
1447
|
+
txt = ts.getElementText( c, cell, cacheIndex );
|
|
1448
|
+
rowData.raw[ cacheIndex ] = txt;
|
|
1449
|
+
val = ts.getParsedText( c, cell, cacheIndex, txt );
|
|
1450
|
+
cells[ cacheIndex ] = val;
|
|
1451
|
+
if ( ( c.parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {
|
|
1452
|
+
// update column max value (ignore sign)
|
|
1453
|
+
c.cache[ tbodyIndex ].colMax[ cacheIndex ] =
|
|
1454
|
+
Math.max( Math.abs( val ) || 0, c.cache[ tbodyIndex ].colMax[ cacheIndex ] || 0 );
|
|
547
1455
|
}
|
|
1456
|
+
span = cell.colSpan - 1;
|
|
1457
|
+
if ( span > 0 ) {
|
|
1458
|
+
cacheIndex += span;
|
|
1459
|
+
}
|
|
1460
|
+
cacheIndex++;
|
|
548
1461
|
}
|
|
1462
|
+
// add the row data to the end
|
|
1463
|
+
cells[ c.columns ] = rowData;
|
|
1464
|
+
// update cache
|
|
1465
|
+
c.cache[ tbodyIndex ].normalized[ order ] = cells;
|
|
549
1466
|
}
|
|
550
|
-
//
|
|
551
|
-
|
|
552
|
-
var $this = $(this),
|
|
553
|
-
nextSort = this.order[(this.count + 1) % (c.sortReset ? 3 : 2)],
|
|
554
|
-
txt = $this.text() + ': ' +
|
|
555
|
-
ts.language[ $this.hasClass(ts.css.sortAsc) ? 'sortAsc' : $this.hasClass(ts.css.sortDesc) ? 'sortDesc' : 'sortNone' ] +
|
|
556
|
-
ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
|
|
557
|
-
$this.attr('aria-label', txt );
|
|
558
|
-
});
|
|
1467
|
+
// resort using current settings
|
|
1468
|
+
ts.checkResort( c, resort, callback );
|
|
559
1469
|
}
|
|
1470
|
+
},
|
|
560
1471
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
overallWidth = $(table).width();
|
|
566
|
-
// only add col for visible columns - fixes #371
|
|
567
|
-
$(table.tBodies[0]).find("tr:first").children(":visible").each(function() {
|
|
568
|
-
colgroup.append($('<col>').css('width', parseInt(($(this).width()/overallWidth)*1000, 10)/10 + '%'));
|
|
569
|
-
});
|
|
570
|
-
$(table).prepend(colgroup);
|
|
571
|
-
}
|
|
1472
|
+
updateCache : function( c, callback, $tbodies ) {
|
|
1473
|
+
// rebuild parsers
|
|
1474
|
+
if ( !( c.parsers && c.parsers.length ) ) {
|
|
1475
|
+
ts.setupParsers( c, $tbodies );
|
|
572
1476
|
}
|
|
1477
|
+
// rebuild the cache map
|
|
1478
|
+
ts.buildCache( c, callback, $tbodies );
|
|
1479
|
+
},
|
|
573
1480
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
o.count = o.count + 1;
|
|
604
|
-
t = o.order[(o.count) % (c.sortReset ? 3 : 2)];
|
|
605
|
-
break;
|
|
606
|
-
default: // ascending
|
|
607
|
-
t = 0;
|
|
608
|
-
break;
|
|
1481
|
+
// init flag (true) used by pager plugin to prevent widget application
|
|
1482
|
+
// renamed from appendToTable
|
|
1483
|
+
appendCache : function( c, init ) {
|
|
1484
|
+
var parsed, totalRows, $tbody, $curTbody, rowIndex, tbodyIndex, appendTime,
|
|
1485
|
+
table = c.table,
|
|
1486
|
+
$tbodies = c.$tbodies,
|
|
1487
|
+
rows = [],
|
|
1488
|
+
cache = c.cache;
|
|
1489
|
+
// empty table - fixes #206/#346
|
|
1490
|
+
if ( ts.isEmptyObject( cache ) ) {
|
|
1491
|
+
// run pager appender in case the table was just emptied
|
|
1492
|
+
return c.appender ? c.appender( table, rows ) :
|
|
1493
|
+
table.isUpdating ? c.$table.triggerHandler( 'updateComplete', table ) : ''; // Fixes #532
|
|
1494
|
+
}
|
|
1495
|
+
if ( ts.debug(c, 'core') ) {
|
|
1496
|
+
appendTime = new Date();
|
|
1497
|
+
}
|
|
1498
|
+
for ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
|
1499
|
+
$tbody = $tbodies.eq( tbodyIndex );
|
|
1500
|
+
if ( $tbody.length ) {
|
|
1501
|
+
// detach tbody for manipulation
|
|
1502
|
+
$curTbody = ts.processTbody( table, $tbody, true );
|
|
1503
|
+
parsed = cache[ tbodyIndex ].normalized;
|
|
1504
|
+
totalRows = parsed.length;
|
|
1505
|
+
for ( rowIndex = 0; rowIndex < totalRows; rowIndex++ ) {
|
|
1506
|
+
rows[rows.length] = parsed[ rowIndex ][ c.columns ].$row;
|
|
1507
|
+
// removeRows used by the pager plugin; don't render if using ajax - fixes #411
|
|
1508
|
+
if ( !c.appender || ( c.pager && !c.pager.removeRows && !c.pager.ajax ) ) {
|
|
1509
|
+
$curTbody.append( parsed[ rowIndex ][ c.columns ].$row );
|
|
609
1510
|
}
|
|
610
|
-
primary = i === 0 ? t : primary;
|
|
611
|
-
s = [ col, parseInt(t, 10) || 0 ];
|
|
612
|
-
c.sortList.push(s);
|
|
613
|
-
t = $.inArray(s[1], o.order); // fixes issue #167
|
|
614
|
-
o.count = t >= 0 ? t : s[1] % (c.sortReset ? 3 : 2);
|
|
615
1511
|
}
|
|
616
|
-
|
|
1512
|
+
// restore tbody
|
|
1513
|
+
ts.processTbody( table, $curTbody, false );
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
if ( c.appender ) {
|
|
1517
|
+
c.appender( table, rows );
|
|
1518
|
+
}
|
|
1519
|
+
if ( ts.debug(c, 'core') ) {
|
|
1520
|
+
console.log( 'Rebuilt table' + ts.benchmark( appendTime ) );
|
|
1521
|
+
}
|
|
1522
|
+
// apply table widgets; but not before ajax completes
|
|
1523
|
+
if ( !init && !c.appender ) {
|
|
1524
|
+
ts.applyWidget( table );
|
|
1525
|
+
}
|
|
1526
|
+
if ( table.isUpdating ) {
|
|
1527
|
+
c.$table.triggerHandler( 'updateComplete', table );
|
|
1528
|
+
}
|
|
1529
|
+
},
|
|
1530
|
+
|
|
1531
|
+
commonUpdate : function( c, resort, callback ) {
|
|
1532
|
+
// remove rows/elements before update
|
|
1533
|
+
c.$table.find( c.selectorRemove ).remove();
|
|
1534
|
+
// rebuild parsers
|
|
1535
|
+
ts.setupParsers( c );
|
|
1536
|
+
// rebuild the cache map
|
|
1537
|
+
ts.buildCache( c );
|
|
1538
|
+
ts.checkResort( c, resort, callback );
|
|
1539
|
+
},
|
|
1540
|
+
|
|
1541
|
+
/*
|
|
1542
|
+
▄█████ ▄████▄ █████▄ ██████ ██ █████▄ ▄████▄
|
|
1543
|
+
▀█▄ ██ ██ ██▄▄██ ██ ██ ██ ██ ██ ▄▄▄
|
|
1544
|
+
▀█▄ ██ ██ ██▀██ ██ ██ ██ ██ ██ ▀██
|
|
1545
|
+
█████▀ ▀████▀ ██ ██ ██ ██ ██ ██ ▀████▀
|
|
1546
|
+
*/
|
|
1547
|
+
initSort : function( c, cell, event ) {
|
|
1548
|
+
if ( c.table.isUpdating ) {
|
|
1549
|
+
// let any updates complete before initializing a sort
|
|
1550
|
+
return setTimeout( function() {
|
|
1551
|
+
ts.initSort( c, cell, event );
|
|
1552
|
+
}, 50 );
|
|
617
1553
|
}
|
|
618
1554
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
1555
|
+
var arry, indx, headerIndx, dir, temp, tmp, $header,
|
|
1556
|
+
notMultiSort = !event[ c.sortMultiSortKey ],
|
|
1557
|
+
table = c.table,
|
|
1558
|
+
len = c.$headers.length,
|
|
1559
|
+
th = ts.getClosest( $( cell ), 'th, td' ),
|
|
1560
|
+
col = parseInt( th.attr( 'data-column' ), 10 ),
|
|
1561
|
+
sortedBy = event.type === 'mouseup' ? 'user' : event.type,
|
|
1562
|
+
order = c.sortVars[ col ].order;
|
|
1563
|
+
th = th[0];
|
|
1564
|
+
// Only call sortStart if sorting is enabled
|
|
1565
|
+
c.$table.triggerHandler( 'sortStart', table );
|
|
1566
|
+
// get current column sort order
|
|
1567
|
+
tmp = ( c.sortVars[ col ].count + 1 ) % order.length;
|
|
1568
|
+
c.sortVars[ col ].count = event[ c.sortResetKey ] ? 2 : tmp;
|
|
1569
|
+
// reset all sorts on non-current column - issue #30
|
|
1570
|
+
if ( c.sortRestart ) {
|
|
1571
|
+
for ( headerIndx = 0; headerIndx < len; headerIndx++ ) {
|
|
1572
|
+
$header = c.$headers.eq( headerIndx );
|
|
1573
|
+
tmp = parseInt( $header.attr( 'data-column' ), 10 );
|
|
1574
|
+
// only reset counts on columns that weren't just clicked on and if not included in a multisort
|
|
1575
|
+
if ( col !== tmp && ( notMultiSort || $header.hasClass( ts.css.sortNone ) ) ) {
|
|
1576
|
+
c.sortVars[ tmp ].count = -1;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
// user only wants to sort on one column
|
|
1581
|
+
if ( notMultiSort ) {
|
|
1582
|
+
$.each( c.sortVars, function( i ) {
|
|
1583
|
+
c.sortVars[ i ].sortedBy = '';
|
|
1584
|
+
});
|
|
1585
|
+
// flush the sort list
|
|
1586
|
+
c.sortList = [];
|
|
1587
|
+
c.last.sortList = [];
|
|
1588
|
+
if ( c.sortForce !== null ) {
|
|
1589
|
+
arry = c.sortForce;
|
|
1590
|
+
for ( indx = 0; indx < arry.length; indx++ ) {
|
|
1591
|
+
if ( arry[ indx ][ 0 ] !== col ) {
|
|
1592
|
+
c.sortList[ c.sortList.length ] = arry[ indx ];
|
|
1593
|
+
c.sortVars[ arry[ indx ][ 0 ] ].sortedBy = 'sortForce';
|
|
643
1594
|
}
|
|
644
|
-
}
|
|
1595
|
+
}
|
|
645
1596
|
}
|
|
646
|
-
//
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
if (
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
1597
|
+
// add column to sort list
|
|
1598
|
+
dir = order[ c.sortVars[ col ].count ];
|
|
1599
|
+
if ( dir < 2 ) {
|
|
1600
|
+
c.sortList[ c.sortList.length ] = [ col, dir ];
|
|
1601
|
+
c.sortVars[ col ].sortedBy = sortedBy;
|
|
1602
|
+
// add other columns if header spans across multiple
|
|
1603
|
+
if ( th.colSpan > 1 ) {
|
|
1604
|
+
for ( indx = 1; indx < th.colSpan; indx++ ) {
|
|
1605
|
+
c.sortList[ c.sortList.length ] = [ col + indx, dir ];
|
|
1606
|
+
// update count on columns in colSpan
|
|
1607
|
+
c.sortVars[ col + indx ].count = $.inArray( dir, order );
|
|
1608
|
+
c.sortVars[ col + indx ].sortedBy = sortedBy;
|
|
658
1609
|
}
|
|
659
1610
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
1611
|
+
}
|
|
1612
|
+
// multi column sorting
|
|
1613
|
+
} else {
|
|
1614
|
+
// get rid of the sortAppend before adding more - fixes issue #115 & #523
|
|
1615
|
+
c.sortList = $.extend( [], c.last.sortList );
|
|
1616
|
+
|
|
1617
|
+
// the user has clicked on an already sorted column
|
|
1618
|
+
if ( ts.isValueInArray( col, c.sortList ) >= 0 ) {
|
|
1619
|
+
// reverse the sorting direction
|
|
1620
|
+
c.sortVars[ col ].sortedBy = sortedBy;
|
|
1621
|
+
for ( indx = 0; indx < c.sortList.length; indx++ ) {
|
|
1622
|
+
tmp = c.sortList[ indx ];
|
|
1623
|
+
if ( tmp[ 0 ] === col ) {
|
|
1624
|
+
// order.count seems to be incorrect when compared to cell.count
|
|
1625
|
+
tmp[ 1 ] = order[ c.sortVars[ col ].count ];
|
|
1626
|
+
if ( tmp[1] === 2 ) {
|
|
1627
|
+
c.sortList.splice( indx, 1 );
|
|
1628
|
+
c.sortVars[ col ].count = -1;
|
|
668
1629
|
}
|
|
669
1630
|
}
|
|
670
1631
|
}
|
|
671
|
-
// multi column sorting
|
|
672
1632
|
} else {
|
|
673
|
-
//
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
1633
|
+
// add column to sort list array
|
|
1634
|
+
dir = order[ c.sortVars[ col ].count ];
|
|
1635
|
+
c.sortVars[ col ].sortedBy = sortedBy;
|
|
1636
|
+
if ( dir < 2 ) {
|
|
1637
|
+
c.sortList[ c.sortList.length ] = [ col, dir ];
|
|
1638
|
+
// add other columns if header spans across multiple
|
|
1639
|
+
if ( th.colSpan > 1 ) {
|
|
1640
|
+
for ( indx = 1; indx < th.colSpan; indx++ ) {
|
|
1641
|
+
c.sortList[ c.sortList.length ] = [ col + indx, dir ];
|
|
1642
|
+
// update count on columns in colSpan
|
|
1643
|
+
c.sortVars[ col + indx ].count = $.inArray( dir, order );
|
|
1644
|
+
c.sortVars[ col + indx ].sortedBy = sortedBy;
|
|
679
1645
|
}
|
|
680
1646
|
}
|
|
681
1647
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
// save sort before applying sortAppend
|
|
1651
|
+
c.last.sortList = $.extend( [], c.sortList );
|
|
1652
|
+
if ( c.sortList.length && c.sortAppend ) {
|
|
1653
|
+
arry = $.isArray( c.sortAppend ) ? c.sortAppend : c.sortAppend[ c.sortList[ 0 ][ 0 ] ];
|
|
1654
|
+
if ( !ts.isEmptyObject( arry ) ) {
|
|
1655
|
+
for ( indx = 0; indx < arry.length; indx++ ) {
|
|
1656
|
+
if ( arry[ indx ][ 0 ] !== col && ts.isValueInArray( arry[ indx ][ 0 ], c.sortList ) < 0 ) {
|
|
1657
|
+
dir = arry[ indx ][ 1 ];
|
|
1658
|
+
temp = ( '' + dir ).match( /^(a|d|s|o|n)/ );
|
|
1659
|
+
if ( temp ) {
|
|
1660
|
+
tmp = c.sortList[ 0 ][ 1 ];
|
|
1661
|
+
switch ( temp[ 0 ] ) {
|
|
1662
|
+
case 'd' :
|
|
1663
|
+
dir = 1;
|
|
1664
|
+
break;
|
|
1665
|
+
case 's' :
|
|
1666
|
+
dir = tmp;
|
|
1667
|
+
break;
|
|
1668
|
+
case 'o' :
|
|
1669
|
+
dir = tmp === 0 ? 1 : 0;
|
|
1670
|
+
break;
|
|
1671
|
+
case 'n' :
|
|
1672
|
+
dir = ( tmp + 1 ) % order.length;
|
|
1673
|
+
break;
|
|
1674
|
+
default:
|
|
1675
|
+
dir = 0;
|
|
1676
|
+
break;
|
|
706
1677
|
}
|
|
707
1678
|
}
|
|
1679
|
+
c.sortList[ c.sortList.length ] = [ arry[ indx ][ 0 ], dir ];
|
|
1680
|
+
c.sortVars[ arry[ indx ][ 0 ] ].sortedBy = 'sortAppend';
|
|
708
1681
|
}
|
|
709
1682
|
}
|
|
710
1683
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1684
|
+
}
|
|
1685
|
+
// sortBegin event triggered immediately before the sort
|
|
1686
|
+
c.$table.triggerHandler( 'sortBegin', table );
|
|
1687
|
+
// setTimeout needed so the processing icon shows up
|
|
1688
|
+
setTimeout( function() {
|
|
1689
|
+
// set css for headers
|
|
1690
|
+
ts.setHeadersCss( c );
|
|
1691
|
+
ts.multisort( c );
|
|
1692
|
+
ts.appendCache( c );
|
|
1693
|
+
c.$table.triggerHandler( 'sortBeforeEnd', table );
|
|
1694
|
+
c.$table.triggerHandler( 'sortEnd', table );
|
|
1695
|
+
}, 1 );
|
|
1696
|
+
},
|
|
1697
|
+
|
|
1698
|
+
// sort multiple columns
|
|
1699
|
+
multisort : function( c ) { /*jshint loopfunc:true */
|
|
1700
|
+
var tbodyIndex, sortTime, colMax, rows, tmp,
|
|
1701
|
+
table = c.table,
|
|
1702
|
+
sorter = [],
|
|
1703
|
+
dir = 0,
|
|
1704
|
+
textSorter = c.textSorter || '',
|
|
1705
|
+
sortList = c.sortList,
|
|
1706
|
+
sortLen = sortList.length,
|
|
1707
|
+
len = c.$tbodies.length;
|
|
1708
|
+
if ( c.serverSideSorting || ts.isEmptyObject( c.cache ) ) {
|
|
1709
|
+
// empty table - fixes #206/#346
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
if ( ts.debug(c, 'core') ) { sortTime = new Date(); }
|
|
1713
|
+
// cache textSorter to optimize speed
|
|
1714
|
+
if ( typeof textSorter === 'object' ) {
|
|
1715
|
+
colMax = c.columns;
|
|
1716
|
+
while ( colMax-- ) {
|
|
1717
|
+
tmp = ts.getColumnData( table, textSorter, colMax );
|
|
1718
|
+
if ( typeof tmp === 'function' ) {
|
|
1719
|
+
sorter[ colMax ] = tmp;
|
|
717
1720
|
}
|
|
718
1721
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
c = table.config,
|
|
737
|
-
cts = c.textSorter || '',
|
|
738
|
-
sortList = c.sortList,
|
|
739
|
-
l = sortList.length,
|
|
740
|
-
bl = table.tBodies.length;
|
|
741
|
-
if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
if (c.debug) { sortTime = new Date(); }
|
|
745
|
-
for (k = 0; k < bl; k++) {
|
|
746
|
-
colMax = c.cache[k].colMax;
|
|
747
|
-
cache = c.cache[k].normalized;
|
|
748
|
-
|
|
749
|
-
cache.sort(function(a, b) {
|
|
750
|
-
// cache is undefined here in IE, so don't use it!
|
|
751
|
-
for (i = 0; i < l; i++) {
|
|
752
|
-
col = sortList[i][0];
|
|
753
|
-
order = sortList[i][1];
|
|
754
|
-
// sort direction, true = asc, false = desc
|
|
755
|
-
dir = order === 0;
|
|
756
|
-
|
|
757
|
-
if (c.sortStable && a[col] === b[col] && l === 1) {
|
|
758
|
-
return a[c.columns].order - b[c.columns].order;
|
|
759
|
-
}
|
|
1722
|
+
}
|
|
1723
|
+
for ( tbodyIndex = 0; tbodyIndex < len; tbodyIndex++ ) {
|
|
1724
|
+
colMax = c.cache[ tbodyIndex ].colMax;
|
|
1725
|
+
rows = c.cache[ tbodyIndex ].normalized;
|
|
1726
|
+
|
|
1727
|
+
rows.sort( function( a, b ) {
|
|
1728
|
+
var sortIndex, num, col, order, sort, x, y;
|
|
1729
|
+
// rows is undefined here in IE, so don't use it!
|
|
1730
|
+
for ( sortIndex = 0; sortIndex < sortLen; sortIndex++ ) {
|
|
1731
|
+
col = sortList[ sortIndex ][ 0 ];
|
|
1732
|
+
order = sortList[ sortIndex ][ 1 ];
|
|
1733
|
+
// sort direction, true = asc, false = desc
|
|
1734
|
+
dir = order === 0;
|
|
1735
|
+
|
|
1736
|
+
if ( c.sortStable && a[ col ] === b[ col ] && sortLen === 1 ) {
|
|
1737
|
+
return a[ c.columns ].order - b[ c.columns ].order;
|
|
1738
|
+
}
|
|
760
1739
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
} else {
|
|
768
|
-
num = (c.strings[col]) ? c.string[c.strings[col]] || 0 : 0;
|
|
769
|
-
}
|
|
770
|
-
// fall back to built-in numeric sort
|
|
771
|
-
// var sort = $.tablesorter["sort" + s](table, a[c], b[c], c, colMax[c], dir);
|
|
772
|
-
sort = c.numberSorter ? c.numberSorter(a[col], b[col], dir, colMax[col], table) :
|
|
773
|
-
ts[ 'sortNumeric' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], num, colMax[col], col, table);
|
|
1740
|
+
// fallback to natural sort since it is more robust
|
|
1741
|
+
num = /n/i.test( ts.getSortType( c.parsers, col ) );
|
|
1742
|
+
if ( num && c.strings[ col ] ) {
|
|
1743
|
+
// sort strings in numerical columns
|
|
1744
|
+
if ( typeof ( ts.string[ c.strings[ col ] ] ) === 'boolean' ) {
|
|
1745
|
+
num = ( dir ? 1 : -1 ) * ( ts.string[ c.strings[ col ] ] ? -1 : 1 );
|
|
774
1746
|
} else {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1747
|
+
num = ( c.strings[ col ] ) ? ts.string[ c.strings[ col ] ] || 0 : 0;
|
|
1748
|
+
}
|
|
1749
|
+
// fall back to built-in numeric sort
|
|
1750
|
+
// var sort = $.tablesorter['sort' + s]( a[col], b[col], dir, colMax[col], table );
|
|
1751
|
+
sort = c.numberSorter ? c.numberSorter( a[ col ], b[ col ], dir, colMax[ col ], table ) :
|
|
1752
|
+
ts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], num, colMax[ col ], col, c );
|
|
1753
|
+
} else {
|
|
1754
|
+
// set a & b depending on sort direction
|
|
1755
|
+
x = dir ? a : b;
|
|
1756
|
+
y = dir ? b : a;
|
|
1757
|
+
// text sort function
|
|
1758
|
+
if ( typeof textSorter === 'function' ) {
|
|
1759
|
+
// custom OVERALL text sorter
|
|
1760
|
+
sort = textSorter( x[ col ], y[ col ], dir, col, table );
|
|
1761
|
+
} else if ( typeof sorter[ col ] === 'function' ) {
|
|
1762
|
+
// custom text sorter for a SPECIFIC COLUMN
|
|
1763
|
+
sort = sorter[ col ]( x[ col ], y[ col ], dir, col, table );
|
|
1764
|
+
} else {
|
|
1765
|
+
// fall back to natural sort
|
|
1766
|
+
sort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ] || '', b[ col ] || '', col, c );
|
|
789
1767
|
}
|
|
790
|
-
if (sort) { return sort; }
|
|
791
1768
|
}
|
|
792
|
-
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
|
|
1769
|
+
if ( sort ) { return sort; }
|
|
1770
|
+
}
|
|
1771
|
+
return a[ c.columns ].order - b[ c.columns ].order;
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1774
|
+
if ( ts.debug(c, 'core') ) {
|
|
1775
|
+
console.log( 'Applying sort ' + sortList.toString() + ts.benchmark( sortTime ) );
|
|
796
1776
|
}
|
|
1777
|
+
},
|
|
797
1778
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
callback($table[0]);
|
|
805
|
-
}
|
|
1779
|
+
resortComplete : function( c, callback ) {
|
|
1780
|
+
if ( c.table.isUpdating ) {
|
|
1781
|
+
c.$table.triggerHandler( 'updateComplete', c.table );
|
|
1782
|
+
}
|
|
1783
|
+
if ( $.isFunction( callback ) ) {
|
|
1784
|
+
callback( c.table );
|
|
806
1785
|
}
|
|
1786
|
+
},
|
|
807
1787
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
//
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1788
|
+
checkResort : function( c, resort, callback ) {
|
|
1789
|
+
var sortList = $.isArray( resort ) ? resort : c.sortList,
|
|
1790
|
+
// if no resort parameter is passed, fallback to config.resort (true by default)
|
|
1791
|
+
resrt = typeof resort === 'undefined' ? c.resort : resort;
|
|
1792
|
+
// don't try to resort if the table is still processing
|
|
1793
|
+
// this will catch spamming of the updateCell method
|
|
1794
|
+
if ( resrt !== false && !c.serverSideSorting && !c.table.isProcessing ) {
|
|
1795
|
+
if ( sortList.length ) {
|
|
1796
|
+
ts.sortOn( c, sortList, function() {
|
|
1797
|
+
ts.resortComplete( c, callback );
|
|
1798
|
+
}, true );
|
|
816
1799
|
} else {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1800
|
+
ts.sortReset( c, function() {
|
|
1801
|
+
ts.resortComplete( c, callback );
|
|
1802
|
+
ts.applyWidget( c.table, false );
|
|
1803
|
+
} );
|
|
1804
|
+
}
|
|
1805
|
+
} else {
|
|
1806
|
+
ts.resortComplete( c, callback );
|
|
1807
|
+
ts.applyWidget( c.table, false );
|
|
820
1808
|
}
|
|
1809
|
+
},
|
|
821
1810
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
.bind("updateCell" + c.namespace, function(e, cell, resort, callback) {
|
|
856
|
-
e.stopPropagation();
|
|
857
|
-
table.isUpdating = true;
|
|
858
|
-
$table.find(c.selectorRemove).remove();
|
|
859
|
-
// get position from the dom
|
|
860
|
-
var v, t, row, icell,
|
|
861
|
-
$tb = $table.find('tbody'),
|
|
862
|
-
$cell = $(cell),
|
|
863
|
-
// update cache - format: function(s, table, cell, cellIndex)
|
|
864
|
-
// no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
|
|
865
|
-
tbdy = $tb.index( $.fn.closest ? $cell.closest('tbody') : $cell.parents('tbody').filter(':first') ),
|
|
866
|
-
$row = $.fn.closest ? $cell.closest('tr') : $cell.parents('tr').filter(':first');
|
|
867
|
-
cell = $cell[0]; // in case cell is a jQuery object
|
|
868
|
-
// tbody may not exist if update is initialized while tbody is removed for processing
|
|
869
|
-
if ($tb.length && tbdy >= 0) {
|
|
870
|
-
row = $tb.eq(tbdy).find('tr').index( $row );
|
|
871
|
-
icell = $cell.index();
|
|
872
|
-
c.cache[tbdy].normalized[row][c.columns].$row = $row;
|
|
873
|
-
if (typeof c.extractors[icell].id === 'undefined') {
|
|
874
|
-
t = getElementText(table, cell, icell);
|
|
875
|
-
} else {
|
|
876
|
-
t = c.extractors[icell].format( getElementText(table, cell, icell), table, cell, icell );
|
|
877
|
-
}
|
|
878
|
-
v = c.parsers[icell].id === 'no-parser' ? '' :
|
|
879
|
-
c.parsers[icell].format( t, table, cell, icell );
|
|
880
|
-
c.cache[tbdy].normalized[row][icell] = c.ignoreCase && typeof v === 'string' ? v.toLowerCase() : v;
|
|
881
|
-
if ((c.parsers[icell].type || '').toLowerCase() === "numeric") {
|
|
882
|
-
// update column max value (ignore sign)
|
|
883
|
-
c.cache[tbdy].colMax[icell] = Math.max(Math.abs(v) || 0, c.cache[tbdy].colMax[icell] || 0);
|
|
884
|
-
}
|
|
885
|
-
checkResort($table, resort, callback);
|
|
886
|
-
}
|
|
887
|
-
})
|
|
888
|
-
.bind("addRows" + c.namespace, function(e, $row, resort, callback) {
|
|
889
|
-
e.stopPropagation();
|
|
890
|
-
table.isUpdating = true;
|
|
891
|
-
if (isEmptyObject(c.cache)) {
|
|
892
|
-
// empty table, do an update instead - fixes #450
|
|
893
|
-
updateHeader(table);
|
|
894
|
-
commonUpdate(table, resort, callback);
|
|
895
|
-
} else {
|
|
896
|
-
$row = $($row).attr('role', 'row'); // make sure we're using a jQuery object
|
|
897
|
-
var i, j, l, t, v, rowData, cells,
|
|
898
|
-
rows = $row.filter('tr').length,
|
|
899
|
-
tbdy = $table.find('tbody').index( $row.parents('tbody').filter(':first') );
|
|
900
|
-
// fixes adding rows to an empty table - see issue #179
|
|
901
|
-
if (!(c.parsers && c.parsers.length)) {
|
|
902
|
-
buildParserCache(table);
|
|
903
|
-
}
|
|
904
|
-
// add each row
|
|
905
|
-
for (i = 0; i < rows; i++) {
|
|
906
|
-
l = $row[i].cells.length;
|
|
907
|
-
cells = [];
|
|
908
|
-
rowData = {
|
|
909
|
-
child: [],
|
|
910
|
-
$row : $row.eq(i),
|
|
911
|
-
order: c.cache[tbdy].normalized.length
|
|
912
|
-
};
|
|
913
|
-
// add each cell
|
|
914
|
-
for (j = 0; j < l; j++) {
|
|
915
|
-
if (typeof c.extractors[j].id === 'undefined') {
|
|
916
|
-
t = getElementText(table, $row[i].cells[j], j);
|
|
917
|
-
} else {
|
|
918
|
-
t = c.extractors[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j );
|
|
919
|
-
}
|
|
920
|
-
v = c.parsers[j].id === 'no-parser' ? '' :
|
|
921
|
-
c.parsers[j].format( t, table, $row[i].cells[j], j );
|
|
922
|
-
cells[j] = c.ignoreCase && typeof v === 'string' ? v.toLowerCase() : v;
|
|
923
|
-
if ((c.parsers[j].type || '').toLowerCase() === "numeric") {
|
|
924
|
-
// update column max value (ignore sign)
|
|
925
|
-
c.cache[tbdy].colMax[j] = Math.max(Math.abs(cells[j]) || 0, c.cache[tbdy].colMax[j] || 0);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
// add the row data to the end
|
|
929
|
-
cells.push(rowData);
|
|
930
|
-
// update cache
|
|
931
|
-
c.cache[tbdy].normalized.push(cells);
|
|
932
|
-
}
|
|
933
|
-
// resort using current settings
|
|
934
|
-
checkResort($table, resort, callback);
|
|
935
|
-
}
|
|
936
|
-
})
|
|
937
|
-
.bind("updateComplete" + c.namespace, function(){
|
|
938
|
-
table.isUpdating = false;
|
|
939
|
-
})
|
|
940
|
-
.bind("sorton" + c.namespace, function(e, list, callback, init) {
|
|
941
|
-
var c = table.config;
|
|
942
|
-
e.stopPropagation();
|
|
943
|
-
$table.trigger("sortStart", this);
|
|
944
|
-
// update header count index
|
|
945
|
-
updateHeaderSortCount(table, list);
|
|
946
|
-
// set css for headers
|
|
947
|
-
setHeadersCss(table);
|
|
948
|
-
// fixes #346
|
|
949
|
-
if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); }
|
|
950
|
-
$table.trigger("sortBegin", this);
|
|
951
|
-
// sort the table and append it to the dom
|
|
952
|
-
multisort(table);
|
|
953
|
-
appendToTable(table, init);
|
|
954
|
-
$table.trigger("sortEnd", this);
|
|
955
|
-
ts.applyWidget(table);
|
|
956
|
-
if ($.isFunction(callback)) {
|
|
957
|
-
callback(table);
|
|
958
|
-
}
|
|
959
|
-
})
|
|
960
|
-
.bind("appendCache" + c.namespace, function(e, callback, init) {
|
|
961
|
-
e.stopPropagation();
|
|
962
|
-
appendToTable(table, init);
|
|
963
|
-
if ($.isFunction(callback)) {
|
|
964
|
-
callback(table);
|
|
965
|
-
}
|
|
966
|
-
})
|
|
967
|
-
.bind("updateCache" + c.namespace, function(e, callback){
|
|
968
|
-
// rebuild parsers
|
|
969
|
-
if (!(c.parsers && c.parsers.length)) {
|
|
970
|
-
buildParserCache(table);
|
|
971
|
-
}
|
|
972
|
-
// rebuild the cache map
|
|
973
|
-
buildCache(table);
|
|
974
|
-
if ($.isFunction(callback)) {
|
|
975
|
-
callback(table);
|
|
976
|
-
}
|
|
977
|
-
})
|
|
978
|
-
.bind("applyWidgetId" + c.namespace, function(e, id) {
|
|
979
|
-
e.stopPropagation();
|
|
980
|
-
ts.getWidgetById(id).format(table, c, c.widgetOptions);
|
|
981
|
-
})
|
|
982
|
-
.bind("applyWidgets" + c.namespace, function(e, init) {
|
|
983
|
-
e.stopPropagation();
|
|
984
|
-
// apply widgets
|
|
985
|
-
ts.applyWidget(table, init);
|
|
986
|
-
})
|
|
987
|
-
.bind("refreshWidgets" + c.namespace, function(e, all, dontapply){
|
|
988
|
-
e.stopPropagation();
|
|
989
|
-
ts.refreshWidgets(table, all, dontapply);
|
|
990
|
-
})
|
|
991
|
-
.bind("destroy" + c.namespace, function(e, c, cb){
|
|
992
|
-
e.stopPropagation();
|
|
993
|
-
ts.destroy(table, c, cb);
|
|
994
|
-
})
|
|
995
|
-
.bind("resetToLoadState" + c.namespace, function(){
|
|
996
|
-
// remove all widgets
|
|
997
|
-
ts.refreshWidgets(table, true, true);
|
|
998
|
-
// restore original settings; this clears out current settings, but does not clear
|
|
999
|
-
// values saved to storage.
|
|
1000
|
-
c = $.extend(true, ts.defaults, c.originalSettings);
|
|
1001
|
-
table.hasInitialized = false;
|
|
1002
|
-
// setup the entire table again
|
|
1003
|
-
ts.setup( table, c );
|
|
1004
|
-
});
|
|
1811
|
+
sortOn : function( c, list, callback, init ) {
|
|
1812
|
+
var indx,
|
|
1813
|
+
table = c.table;
|
|
1814
|
+
c.$table.triggerHandler( 'sortStart', table );
|
|
1815
|
+
for (indx = 0; indx < c.columns; indx++) {
|
|
1816
|
+
c.sortVars[ indx ].sortedBy = ts.isValueInArray( indx, list ) > -1 ? 'sorton' : '';
|
|
1817
|
+
}
|
|
1818
|
+
// update header count index
|
|
1819
|
+
ts.updateHeaderSortCount( c, list );
|
|
1820
|
+
// set css for headers
|
|
1821
|
+
ts.setHeadersCss( c );
|
|
1822
|
+
// fixes #346
|
|
1823
|
+
if ( c.delayInit && ts.isEmptyObject( c.cache ) ) {
|
|
1824
|
+
ts.buildCache( c );
|
|
1825
|
+
}
|
|
1826
|
+
c.$table.triggerHandler( 'sortBegin', table );
|
|
1827
|
+
// sort the table and append it to the dom
|
|
1828
|
+
ts.multisort( c );
|
|
1829
|
+
ts.appendCache( c, init );
|
|
1830
|
+
c.$table.triggerHandler( 'sortBeforeEnd', table );
|
|
1831
|
+
c.$table.triggerHandler( 'sortEnd', table );
|
|
1832
|
+
ts.applyWidget( table );
|
|
1833
|
+
if ( $.isFunction( callback ) ) {
|
|
1834
|
+
callback( table );
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
|
|
1838
|
+
sortReset : function( c, callback ) {
|
|
1839
|
+
c.sortList = [];
|
|
1840
|
+
var indx;
|
|
1841
|
+
for (indx = 0; indx < c.columns; indx++) {
|
|
1842
|
+
c.sortVars[ indx ].count = -1;
|
|
1843
|
+
c.sortVars[ indx ].sortedBy = '';
|
|
1005
1844
|
}
|
|
1845
|
+
ts.setHeadersCss( c );
|
|
1846
|
+
ts.multisort( c );
|
|
1847
|
+
ts.appendCache( c );
|
|
1848
|
+
if ( $.isFunction( callback ) ) {
|
|
1849
|
+
callback( c.table );
|
|
1850
|
+
}
|
|
1851
|
+
},
|
|
1006
1852
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
var table = this,
|
|
1011
|
-
// merge & extend config options
|
|
1012
|
-
c = $.extend(true, {}, ts.defaults, settings);
|
|
1013
|
-
// save initial settings
|
|
1014
|
-
c.originalSettings = settings;
|
|
1015
|
-
// create a table from data (build table widget)
|
|
1016
|
-
if (!table.hasInitialized && ts.buildTable && this.tagName !== 'TABLE') {
|
|
1017
|
-
// return the table (in case the original target is the table's container)
|
|
1018
|
-
ts.buildTable(table, c);
|
|
1019
|
-
} else {
|
|
1020
|
-
ts.setup(table, c);
|
|
1021
|
-
}
|
|
1022
|
-
});
|
|
1023
|
-
};
|
|
1853
|
+
getSortType : function( parsers, column ) {
|
|
1854
|
+
return ( parsers && parsers[ column ] ) ? parsers[ column ].type || '' : '';
|
|
1855
|
+
},
|
|
1024
1856
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
}
|
|
1857
|
+
getOrder : function( val ) {
|
|
1858
|
+
// look for 'd' in 'desc' order; return true
|
|
1859
|
+
return ( /^d/i.test( val ) || val === 1 );
|
|
1860
|
+
},
|
|
1030
1861
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
if (
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
//
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
if (
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
c.namespace = '.' + c.namespace.replace(/\W/g,'');
|
|
1067
|
-
}
|
|
1862
|
+
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
|
1863
|
+
sortNatural : function( a, b ) {
|
|
1864
|
+
if ( a === b ) { return 0; }
|
|
1865
|
+
a = ( a || '' ).toString();
|
|
1866
|
+
b = ( b || '' ).toString();
|
|
1867
|
+
var aNum, bNum, aFloat, bFloat, indx, max,
|
|
1868
|
+
regex = ts.regex;
|
|
1869
|
+
// first try and sort Hex codes
|
|
1870
|
+
if ( regex.hex.test( b ) ) {
|
|
1871
|
+
aNum = parseInt( a.match( regex.hex ), 16 );
|
|
1872
|
+
bNum = parseInt( b.match( regex.hex ), 16 );
|
|
1873
|
+
if ( aNum < bNum ) { return -1; }
|
|
1874
|
+
if ( aNum > bNum ) { return 1; }
|
|
1875
|
+
}
|
|
1876
|
+
// chunk/tokenize
|
|
1877
|
+
aNum = a.replace( regex.chunk, '\\0$1\\0' ).replace( regex.chunks, '' ).split( '\\0' );
|
|
1878
|
+
bNum = b.replace( regex.chunk, '\\0$1\\0' ).replace( regex.chunks, '' ).split( '\\0' );
|
|
1879
|
+
max = Math.max( aNum.length, bNum.length );
|
|
1880
|
+
// natural sorting through split numeric strings and default strings
|
|
1881
|
+
for ( indx = 0; indx < max; indx++ ) {
|
|
1882
|
+
// find floats not starting with '0', string or 0 if not defined
|
|
1883
|
+
aFloat = isNaN( aNum[ indx ] ) ? aNum[ indx ] || 0 : parseFloat( aNum[ indx ] ) || 0;
|
|
1884
|
+
bFloat = isNaN( bNum[ indx ] ) ? bNum[ indx ] || 0 : parseFloat( bNum[ indx ] ) || 0;
|
|
1885
|
+
// handle numeric vs string comparison - number < string - (Kyle Adams)
|
|
1886
|
+
if ( isNaN( aFloat ) !== isNaN( bFloat ) ) { return isNaN( aFloat ) ? 1 : -1; }
|
|
1887
|
+
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
|
1888
|
+
if ( typeof aFloat !== typeof bFloat ) {
|
|
1889
|
+
aFloat += '';
|
|
1890
|
+
bFloat += '';
|
|
1891
|
+
}
|
|
1892
|
+
if ( aFloat < bFloat ) { return -1; }
|
|
1893
|
+
if ( aFloat > bFloat ) { return 1; }
|
|
1894
|
+
}
|
|
1895
|
+
return 0;
|
|
1896
|
+
},
|
|
1068
1897
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
}
|
|
1077
|
-
c.widgetInit = {}; // keep a list of initialized widgets
|
|
1078
|
-
// change textExtraction via data-attribute
|
|
1079
|
-
c.textExtraction = c.$table.attr('data-text-extraction') || c.textExtraction || 'basic';
|
|
1080
|
-
// build headers
|
|
1081
|
-
buildHeaders(table);
|
|
1082
|
-
// fixate columns if the users supplies the fixedWidth option
|
|
1083
|
-
// do this after theme has been applied
|
|
1084
|
-
fixColumnWidth(table);
|
|
1085
|
-
// try to auto detect column type, and store in tables config
|
|
1086
|
-
buildParserCache(table);
|
|
1087
|
-
// start total row count at zero
|
|
1088
|
-
c.totalRows = 0;
|
|
1089
|
-
// build the cache for the tbody cells
|
|
1090
|
-
// delayInit will delay building the cache until the user starts a sort
|
|
1091
|
-
if (!c.delayInit) { buildCache(table); }
|
|
1092
|
-
// bind all header events and methods
|
|
1093
|
-
ts.bindEvents(table, c.$headers, true);
|
|
1094
|
-
bindMethods(table);
|
|
1095
|
-
// get sort list from jQuery data or metadata
|
|
1096
|
-
// in jQuery < 1.4, an error occurs when calling $table.data()
|
|
1097
|
-
if (c.supportsDataObject && typeof $table.data().sortlist !== 'undefined') {
|
|
1098
|
-
c.sortList = $table.data().sortlist;
|
|
1099
|
-
} else if (m && ($table.metadata() && $table.metadata().sortlist)) {
|
|
1100
|
-
c.sortList = $table.metadata().sortlist;
|
|
1101
|
-
}
|
|
1102
|
-
// apply widget init code
|
|
1103
|
-
ts.applyWidget(table, true);
|
|
1104
|
-
// if user has supplied a sort list to constructor
|
|
1105
|
-
if (c.sortList.length > 0) {
|
|
1106
|
-
$table.trigger("sorton", [c.sortList, {}, !c.initWidgets, true]);
|
|
1107
|
-
} else {
|
|
1108
|
-
setHeadersCss(table);
|
|
1109
|
-
if (c.initWidgets) {
|
|
1110
|
-
// apply widget format
|
|
1111
|
-
ts.applyWidget(table, false);
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1898
|
+
sortNaturalAsc : function( a, b, col, c ) {
|
|
1899
|
+
if ( a === b ) { return 0; }
|
|
1900
|
+
var empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];
|
|
1901
|
+
if ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : -empty || -1; }
|
|
1902
|
+
if ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : empty || 1; }
|
|
1903
|
+
return ts.sortNatural( a, b );
|
|
1904
|
+
},
|
|
1114
1905
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1906
|
+
sortNaturalDesc : function( a, b, col, c ) {
|
|
1907
|
+
if ( a === b ) { return 0; }
|
|
1908
|
+
var empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];
|
|
1909
|
+
if ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : empty || 1; }
|
|
1910
|
+
if ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : -empty || -1; }
|
|
1911
|
+
return ts.sortNatural( b, a );
|
|
1912
|
+
},
|
|
1913
|
+
|
|
1914
|
+
// basic alphabetical sort
|
|
1915
|
+
sortText : function( a, b ) {
|
|
1916
|
+
return a > b ? 1 : ( a < b ? -1 : 0 );
|
|
1917
|
+
},
|
|
1918
|
+
|
|
1919
|
+
// return text string value by adding up ascii value
|
|
1920
|
+
// so the text is somewhat sorted when using a digital sort
|
|
1921
|
+
// this is NOT an alphanumeric sort
|
|
1922
|
+
getTextValue : function( val, num, max ) {
|
|
1923
|
+
if ( max ) {
|
|
1924
|
+
// make sure the text value is greater than the max numerical value (max)
|
|
1925
|
+
var indx,
|
|
1926
|
+
len = val ? val.length : 0,
|
|
1927
|
+
n = max + num;
|
|
1928
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1929
|
+
n += val.charCodeAt( indx );
|
|
1930
|
+
}
|
|
1931
|
+
return num * n;
|
|
1932
|
+
}
|
|
1933
|
+
return 0;
|
|
1934
|
+
},
|
|
1935
|
+
|
|
1936
|
+
sortNumericAsc : function( a, b, num, max, col, c ) {
|
|
1937
|
+
if ( a === b ) { return 0; }
|
|
1938
|
+
var empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];
|
|
1939
|
+
if ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : -empty || -1; }
|
|
1940
|
+
if ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : empty || 1; }
|
|
1941
|
+
if ( isNaN( a ) ) { a = ts.getTextValue( a, num, max ); }
|
|
1942
|
+
if ( isNaN( b ) ) { b = ts.getTextValue( b, num, max ); }
|
|
1943
|
+
return a - b;
|
|
1944
|
+
},
|
|
1129
1945
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1946
|
+
sortNumericDesc : function( a, b, num, max, col, c ) {
|
|
1947
|
+
if ( a === b ) { return 0; }
|
|
1948
|
+
var empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];
|
|
1949
|
+
if ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : empty || 1; }
|
|
1950
|
+
if ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : -empty || -1; }
|
|
1951
|
+
if ( isNaN( a ) ) { a = ts.getTextValue( a, num, max ); }
|
|
1952
|
+
if ( isNaN( b ) ) { b = ts.getTextValue( b, num, max ); }
|
|
1953
|
+
return b - a;
|
|
1954
|
+
},
|
|
1955
|
+
|
|
1956
|
+
sortNumeric : function( a, b ) {
|
|
1957
|
+
return a - b;
|
|
1958
|
+
},
|
|
1959
|
+
|
|
1960
|
+
/*
|
|
1961
|
+
██ ██ ██ ██ █████▄ ▄████▄ ██████ ██████ ▄█████
|
|
1962
|
+
██ ██ ██ ██ ██ ██ ██ ▄▄▄ ██▄▄ ██ ▀█▄
|
|
1963
|
+
██ ██ ██ ██ ██ ██ ██ ▀██ ██▀▀ ██ ▀█▄
|
|
1964
|
+
███████▀ ██ █████▀ ▀████▀ ██████ ██ █████▀
|
|
1965
|
+
*/
|
|
1966
|
+
addWidget : function( widget ) {
|
|
1967
|
+
if ( widget.id && !ts.isEmptyObject( ts.getWidgetById( widget.id ) ) ) {
|
|
1968
|
+
console.warn( '"' + widget.id + '" widget was loaded more than once!' );
|
|
1969
|
+
}
|
|
1970
|
+
ts.widgets[ ts.widgets.length ] = widget;
|
|
1971
|
+
},
|
|
1972
|
+
|
|
1973
|
+
hasWidget : function( $table, name ) {
|
|
1974
|
+
$table = $( $table );
|
|
1975
|
+
return $table.length && $table[ 0 ].config && $table[ 0 ].config.widgetInit[ name ] || false;
|
|
1976
|
+
},
|
|
1977
|
+
|
|
1978
|
+
getWidgetById : function( name ) {
|
|
1979
|
+
var indx, widget,
|
|
1980
|
+
len = ts.widgets.length;
|
|
1981
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1982
|
+
widget = ts.widgets[ indx ];
|
|
1983
|
+
if ( widget && widget.id && widget.id.toLowerCase() === name.toLowerCase() ) {
|
|
1984
|
+
return widget;
|
|
1135
1985
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
};
|
|
1986
|
+
}
|
|
1987
|
+
},
|
|
1139
1988
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
$h = c.$headers.eq(indx).filter(k);
|
|
1153
|
-
} else {
|
|
1154
|
-
// get column indexed cell
|
|
1155
|
-
$h = c.$headers.filter('[data-column="' + indx + '"]:last').filter(k);
|
|
1156
|
-
}
|
|
1157
|
-
if ($h.length) {
|
|
1158
|
-
return obj[k];
|
|
1159
|
-
}
|
|
1989
|
+
applyWidgetOptions : function( table ) {
|
|
1990
|
+
var indx, widget, wo,
|
|
1991
|
+
c = table.config,
|
|
1992
|
+
len = c.widgets.length;
|
|
1993
|
+
if ( len ) {
|
|
1994
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
1995
|
+
widget = ts.getWidgetById( c.widgets[ indx ] );
|
|
1996
|
+
if ( widget && widget.options ) {
|
|
1997
|
+
wo = $.extend( true, {}, widget.options );
|
|
1998
|
+
c.widgetOptions = $.extend( true, wo, c.widgetOptions );
|
|
1999
|
+
// add widgetOptions to defaults for option validator
|
|
2000
|
+
$.extend( true, ts.defaults.widgetOptions, widget.options );
|
|
1160
2001
|
}
|
|
1161
2002
|
}
|
|
1162
|
-
|
|
1163
|
-
|
|
2003
|
+
}
|
|
2004
|
+
},
|
|
1164
2005
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
colSpan = cell.colSpan || 1;
|
|
1182
|
-
if (typeof(matrix[rowIndex]) === "undefined") {
|
|
1183
|
-
matrix[rowIndex] = [];
|
|
1184
|
-
}
|
|
1185
|
-
// Find first available column in the first row
|
|
1186
|
-
for (k = 0; k < matrix[rowIndex].length + 1; k++) {
|
|
1187
|
-
if (typeof(matrix[rowIndex][k]) === "undefined") {
|
|
1188
|
-
firstAvailCol = k;
|
|
1189
|
-
break;
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
lookup[cellId] = firstAvailCol;
|
|
1193
|
-
cols = Math.max(firstAvailCol, cols);
|
|
1194
|
-
// add data-column
|
|
1195
|
-
$cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex
|
|
1196
|
-
for (k = rowIndex; k < rowIndex + rowSpan; k++) {
|
|
1197
|
-
if (typeof(matrix[k]) === "undefined") {
|
|
1198
|
-
matrix[k] = [];
|
|
1199
|
-
}
|
|
1200
|
-
matrixrow = matrix[k];
|
|
1201
|
-
for (l = firstAvailCol; l < firstAvailCol + colSpan; l++) {
|
|
1202
|
-
matrixrow[l] = "x";
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
2006
|
+
addWidgetFromClass : function( table ) {
|
|
2007
|
+
var len, indx,
|
|
2008
|
+
c = table.config,
|
|
2009
|
+
// look for widgets to apply from table class
|
|
2010
|
+
// don't match from 'ui-widget-content'; use \S instead of \w to include widgets
|
|
2011
|
+
// with dashes in the name, e.g. "widget-test-2" extracts out "test-2"
|
|
2012
|
+
regex = '^' + c.widgetClass.replace( ts.regex.templateName, '(\\S+)+' ) + '$',
|
|
2013
|
+
widgetClass = new RegExp( regex, 'g' ),
|
|
2014
|
+
// split up table class (widget id's can include dashes) - stop using match
|
|
2015
|
+
// otherwise only one widget gets extracted, see #1109
|
|
2016
|
+
widgets = ( table.className || '' ).split( ts.regex.spaces );
|
|
2017
|
+
if ( widgets.length ) {
|
|
2018
|
+
len = widgets.length;
|
|
2019
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2020
|
+
if ( widgets[ indx ].match( widgetClass ) ) {
|
|
2021
|
+
c.widgets[ c.widgets.length ] = widgets[ indx ].replace( widgetClass, '$1' );
|
|
1205
2022
|
}
|
|
1206
2023
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
};
|
|
2024
|
+
}
|
|
2025
|
+
},
|
|
1210
2026
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
2027
|
+
applyWidgetId : function( table, id, init ) {
|
|
2028
|
+
table = $(table)[0];
|
|
2029
|
+
var applied, time, name,
|
|
2030
|
+
c = table.config,
|
|
2031
|
+
wo = c.widgetOptions,
|
|
2032
|
+
debug = ts.debug(c, 'core'),
|
|
2033
|
+
widget = ts.getWidgetById( id );
|
|
2034
|
+
if ( widget ) {
|
|
2035
|
+
name = widget.id;
|
|
2036
|
+
applied = false;
|
|
2037
|
+
// add widget name to option list so it gets reapplied after sorting, filtering, etc
|
|
2038
|
+
if ( $.inArray( name, c.widgets ) < 0 ) {
|
|
2039
|
+
c.widgets[ c.widgets.length ] = name;
|
|
2040
|
+
}
|
|
2041
|
+
if ( debug ) { time = new Date(); }
|
|
2042
|
+
|
|
2043
|
+
if ( init || !( c.widgetInit[ name ] ) ) {
|
|
2044
|
+
// set init flag first to prevent calling init more than once (e.g. pager)
|
|
2045
|
+
c.widgetInit[ name ] = true;
|
|
2046
|
+
if ( table.hasInitialized ) {
|
|
2047
|
+
// don't reapply widget options on tablesorter init
|
|
2048
|
+
ts.applyWidgetOptions( table );
|
|
2049
|
+
}
|
|
2050
|
+
if ( typeof widget.init === 'function' ) {
|
|
2051
|
+
applied = true;
|
|
2052
|
+
if ( debug ) {
|
|
2053
|
+
console[ console.group ? 'group' : 'log' ]( 'Initializing ' + name + ' widget' );
|
|
2054
|
+
}
|
|
2055
|
+
widget.init( table, widget, c, wo );
|
|
1226
2056
|
}
|
|
1227
|
-
table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
|
|
1228
|
-
} else {
|
|
1229
|
-
table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
|
|
1230
2057
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
var holdr;
|
|
1238
|
-
if (getIt) {
|
|
1239
|
-
table.isProcessing = true;
|
|
1240
|
-
$tb.before('<span class="tablesorter-savemyplace"/>');
|
|
1241
|
-
holdr = ($.fn.detach) ? $tb.detach() : $tb.remove();
|
|
1242
|
-
return holdr;
|
|
1243
|
-
}
|
|
1244
|
-
holdr = $(table).find('span.tablesorter-savemyplace');
|
|
1245
|
-
$tb.insertAfter( holdr );
|
|
1246
|
-
holdr.remove();
|
|
1247
|
-
table.isProcessing = false;
|
|
1248
|
-
};
|
|
1249
|
-
|
|
1250
|
-
ts.clearTableBody = function(table) {
|
|
1251
|
-
$(table)[0].config.$tbodies.children().detach();
|
|
1252
|
-
};
|
|
1253
|
-
|
|
1254
|
-
ts.bindEvents = function(table, $headers, core){
|
|
1255
|
-
table = $(table)[0];
|
|
1256
|
-
var downTime,
|
|
1257
|
-
c = table.config;
|
|
1258
|
-
if (core !== true) {
|
|
1259
|
-
c.$extraHeaders = c.$extraHeaders ? c.$extraHeaders.add($headers) : $headers;
|
|
2058
|
+
if ( !init && typeof widget.format === 'function' ) {
|
|
2059
|
+
applied = true;
|
|
2060
|
+
if ( debug ) {
|
|
2061
|
+
console[ console.group ? 'group' : 'log' ]( 'Updating ' + name + ' widget' );
|
|
2062
|
+
}
|
|
2063
|
+
widget.format( table, c, wo, false );
|
|
1260
2064
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
.bind('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' '), function(e, external) {
|
|
1267
|
-
var cell, type = e.type;
|
|
1268
|
-
// only recognize left clicks or enter
|
|
1269
|
-
if ( ((e.which || e.button) !== 1 && !/sort|keyup/.test(type)) || (type === 'keyup' && e.which !== 13) ) {
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
// ignore long clicks (prevents resizable widget from initializing a sort)
|
|
1273
|
-
if (type === 'mouseup' && external !== true && (new Date().getTime() - downTime > 250)) { return; }
|
|
1274
|
-
// set timer on mousedown
|
|
1275
|
-
if (type === 'mousedown') {
|
|
1276
|
-
downTime = new Date().getTime();
|
|
1277
|
-
return /(input|select|button|textarea)/i.test(e.target.tagName) ? '' : !c.cancelSelection;
|
|
1278
|
-
}
|
|
1279
|
-
if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); }
|
|
1280
|
-
// jQuery v1.2.6 doesn't have closest()
|
|
1281
|
-
cell = $.fn.closest ? $(this).closest('th, td')[0] : /TH|TD/.test(this.tagName) ? this : $(this).parents('th, td')[0];
|
|
1282
|
-
// reference original table headers and find the same cell
|
|
1283
|
-
cell = c.$headers[ $headers.index( cell ) ];
|
|
1284
|
-
if (!cell.sortDisabled) {
|
|
1285
|
-
initSort(table, cell, e);
|
|
1286
|
-
}
|
|
1287
|
-
});
|
|
1288
|
-
if (c.cancelSelection) {
|
|
1289
|
-
// cancel selection
|
|
1290
|
-
$headers
|
|
1291
|
-
.attr('unselectable', 'on')
|
|
1292
|
-
.bind('selectstart', false)
|
|
1293
|
-
.css({
|
|
1294
|
-
'user-select': 'none',
|
|
1295
|
-
'MozUserSelect': 'none' // not needed for jQuery 1.8+
|
|
1296
|
-
});
|
|
2065
|
+
if ( debug ) {
|
|
2066
|
+
if ( applied ) {
|
|
2067
|
+
console.log( 'Completed ' + ( init ? 'initializing ' : 'applying ' ) + name + ' widget' + ts.benchmark( time ) );
|
|
2068
|
+
if ( console.groupEnd ) { console.groupEnd(); }
|
|
2069
|
+
}
|
|
1297
2070
|
}
|
|
1298
|
-
}
|
|
2071
|
+
}
|
|
2072
|
+
},
|
|
1299
2073
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
2074
|
+
applyWidget : function( table, init, callback ) {
|
|
2075
|
+
table = $( table )[ 0 ]; // in case this is called externally
|
|
2076
|
+
var indx, len, names, widget, time,
|
|
2077
|
+
c = table.config,
|
|
2078
|
+
debug = ts.debug(c, 'core'),
|
|
2079
|
+
widgets = [];
|
|
2080
|
+
// prevent numerous consecutive widget applications
|
|
2081
|
+
if ( init !== false && table.hasInitialized && ( table.isApplyingWidgets || table.isUpdating ) ) {
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
if ( debug ) { time = new Date(); }
|
|
2085
|
+
ts.addWidgetFromClass( table );
|
|
2086
|
+
// prevent "tablesorter-ready" from firing multiple times in a row
|
|
2087
|
+
clearTimeout( c.timerReady );
|
|
2088
|
+
if ( c.widgets.length ) {
|
|
2089
|
+
table.isApplyingWidgets = true;
|
|
2090
|
+
// ensure unique widget ids
|
|
2091
|
+
c.widgets = $.grep( c.widgets, function( val, index ) {
|
|
2092
|
+
return $.inArray( val, c.widgets ) === index;
|
|
2093
|
+
});
|
|
2094
|
+
names = c.widgets || [];
|
|
2095
|
+
len = names.length;
|
|
2096
|
+
// build widget array & add priority as needed
|
|
2097
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2098
|
+
widget = ts.getWidgetById( names[ indx ] );
|
|
2099
|
+
if ( widget && widget.id ) {
|
|
2100
|
+
// set priority to 10 if not defined
|
|
2101
|
+
if ( !widget.priority ) { widget.priority = 10; }
|
|
2102
|
+
widgets[ indx ] = widget;
|
|
2103
|
+
} else if ( debug ) {
|
|
2104
|
+
console.warn( '"' + names[ indx ] + '" was enabled, but the widget code has not been loaded!' );
|
|
1309
2105
|
}
|
|
2106
|
+
}
|
|
2107
|
+
// sort widgets by priority
|
|
2108
|
+
widgets.sort( function( a, b ) {
|
|
2109
|
+
return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1;
|
|
1310
2110
|
});
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
$f = $t.find('tfoot:first > tr').children('th, td');
|
|
1322
|
-
if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) {
|
|
1323
|
-
// reapply uitheme classes, in case we want to maintain appearance
|
|
1324
|
-
$t.trigger('applyWidgetId', ['uitheme']);
|
|
1325
|
-
$t.trigger('applyWidgetId', ['zebra']);
|
|
1326
|
-
}
|
|
1327
|
-
// remove widget added rows, just in case
|
|
1328
|
-
$h.find('tr').not($r).remove();
|
|
1329
|
-
// disable tablesorter
|
|
1330
|
-
$t
|
|
1331
|
-
.removeData('tablesorter')
|
|
1332
|
-
.unbind('sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState '.split(' ').join(c.namespace + ' '));
|
|
1333
|
-
c.$headers.add($f)
|
|
1334
|
-
.removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') )
|
|
1335
|
-
.removeAttr('data-column')
|
|
1336
|
-
.removeAttr('aria-label')
|
|
1337
|
-
.attr('aria-disabled', 'true');
|
|
1338
|
-
$r.find(c.selectorSort).unbind('mousedown mouseup keypress '.split(' ').join(c.namespace + ' '));
|
|
1339
|
-
ts.restoreHeaders(table);
|
|
1340
|
-
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
|
1341
|
-
// clear flag in case the plugin is initialized again
|
|
1342
|
-
table.hasInitialized = false;
|
|
1343
|
-
delete table.config.cache;
|
|
1344
|
-
if (typeof callback === 'function') {
|
|
1345
|
-
callback(table);
|
|
2111
|
+
// add/update selected widgets
|
|
2112
|
+
len = widgets.length;
|
|
2113
|
+
if ( debug ) {
|
|
2114
|
+
console[ console.group ? 'group' : 'log' ]( 'Start ' + ( init ? 'initializing' : 'applying' ) + ' widgets' );
|
|
2115
|
+
}
|
|
2116
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2117
|
+
widget = widgets[ indx ];
|
|
2118
|
+
if ( widget && widget.id ) {
|
|
2119
|
+
ts.applyWidgetId( table, widget.id, init );
|
|
2120
|
+
}
|
|
1346
2121
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
2122
|
+
if ( debug && console.groupEnd ) { console.groupEnd(); }
|
|
2123
|
+
}
|
|
2124
|
+
c.timerReady = setTimeout( function() {
|
|
2125
|
+
table.isApplyingWidgets = false;
|
|
2126
|
+
$.data( table, 'lastWidgetApplication', new Date() );
|
|
2127
|
+
c.$table.triggerHandler( 'tablesorter-ready' );
|
|
2128
|
+
// callback executed on init only
|
|
2129
|
+
if ( !init && typeof callback === 'function' ) {
|
|
2130
|
+
callback( table );
|
|
2131
|
+
}
|
|
2132
|
+
if ( debug ) {
|
|
2133
|
+
widget = c.widgets.length;
|
|
2134
|
+
console.log( 'Completed ' +
|
|
2135
|
+
( init === true ? 'initializing ' : 'applying ' ) + widget +
|
|
2136
|
+
' widget' + ( widget !== 1 ? 's' : '' ) + ts.benchmark( time ) );
|
|
2137
|
+
}
|
|
2138
|
+
}, 10 );
|
|
2139
|
+
},
|
|
1356
2140
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
if ( xD > yD ) { return 1; }
|
|
1370
|
-
}
|
|
1371
|
-
// chunk/tokenize
|
|
1372
|
-
xN = a.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0');
|
|
1373
|
-
yN = b.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0');
|
|
1374
|
-
mx = Math.max(xN.length, yN.length);
|
|
1375
|
-
// natural sorting through split numeric strings and default strings
|
|
1376
|
-
for (i = 0; i < mx; i++) {
|
|
1377
|
-
// find floats not starting with '0', string or 0 if not defined
|
|
1378
|
-
xF = isNaN(xN[i]) ? xN[i] || 0 : parseFloat(xN[i]) || 0;
|
|
1379
|
-
yF = isNaN(yN[i]) ? yN[i] || 0 : parseFloat(yN[i]) || 0;
|
|
1380
|
-
// handle numeric vs string comparison - number < string - (Kyle Adams)
|
|
1381
|
-
if (isNaN(xF) !== isNaN(yF)) { return (isNaN(xF)) ? 1 : -1; }
|
|
1382
|
-
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
|
1383
|
-
if (typeof xF !== typeof yF) {
|
|
1384
|
-
xF += '';
|
|
1385
|
-
yF += '';
|
|
2141
|
+
removeWidget : function( table, name, refreshing ) {
|
|
2142
|
+
table = $( table )[ 0 ];
|
|
2143
|
+
var index, widget, indx, len,
|
|
2144
|
+
c = table.config;
|
|
2145
|
+
// if name === true, add all widgets from $.tablesorter.widgets
|
|
2146
|
+
if ( name === true ) {
|
|
2147
|
+
name = [];
|
|
2148
|
+
len = ts.widgets.length;
|
|
2149
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2150
|
+
widget = ts.widgets[ indx ];
|
|
2151
|
+
if ( widget && widget.id ) {
|
|
2152
|
+
name[ name.length ] = widget.id;
|
|
1386
2153
|
}
|
|
1387
|
-
if (xF < yF) { return -1; }
|
|
1388
|
-
if (xF > yF) { return 1; }
|
|
1389
2154
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
2155
|
+
} else {
|
|
2156
|
+
// name can be either an array of widgets names,
|
|
2157
|
+
// or a space/comma separated list of widget names
|
|
2158
|
+
name = ( $.isArray( name ) ? name.join( ',' ) : name || '' ).toLowerCase().split( /[\s,]+/ );
|
|
2159
|
+
}
|
|
2160
|
+
len = name.length;
|
|
2161
|
+
for ( index = 0; index < len; index++ ) {
|
|
2162
|
+
widget = ts.getWidgetById( name[ index ] );
|
|
2163
|
+
indx = $.inArray( name[ index ], c.widgets );
|
|
2164
|
+
// don't remove the widget from config.widget if refreshing
|
|
2165
|
+
if ( indx >= 0 && refreshing !== true ) {
|
|
2166
|
+
c.widgets.splice( indx, 1 );
|
|
2167
|
+
}
|
|
2168
|
+
if ( widget && widget.remove ) {
|
|
2169
|
+
if ( ts.debug(c, 'core') ) {
|
|
2170
|
+
console.log( ( refreshing ? 'Refreshing' : 'Removing' ) + ' "' + name[ index ] + '" widget' );
|
|
2171
|
+
}
|
|
2172
|
+
widget.remove( table, c, c.widgetOptions, refreshing );
|
|
2173
|
+
c.widgetInit[ name[ index ] ] = false;
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
c.$table.triggerHandler( 'widgetRemoveEnd', table );
|
|
2177
|
+
},
|
|
1392
2178
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
2179
|
+
refreshWidgets : function( table, doAll, dontapply ) {
|
|
2180
|
+
table = $( table )[ 0 ]; // see issue #243
|
|
2181
|
+
var indx, widget,
|
|
2182
|
+
c = table.config,
|
|
2183
|
+
curWidgets = c.widgets,
|
|
2184
|
+
widgets = ts.widgets,
|
|
2185
|
+
len = widgets.length,
|
|
2186
|
+
list = [],
|
|
2187
|
+
callback = function( table ) {
|
|
2188
|
+
$( table ).triggerHandler( 'refreshComplete' );
|
|
2189
|
+
};
|
|
2190
|
+
// remove widgets not defined in config.widgets, unless doAll is true
|
|
2191
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2192
|
+
widget = widgets[ indx ];
|
|
2193
|
+
if ( widget && widget.id && ( doAll || $.inArray( widget.id, curWidgets ) < 0 ) ) {
|
|
2194
|
+
list[ list.length ] = widget.id;
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
ts.removeWidget( table, list.join( ',' ), true );
|
|
2198
|
+
if ( dontapply !== true ) {
|
|
2199
|
+
// call widget init if
|
|
2200
|
+
ts.applyWidget( table, doAll || false, callback );
|
|
2201
|
+
if ( doAll ) {
|
|
2202
|
+
// apply widget format
|
|
2203
|
+
ts.applyWidget( table, false, callback );
|
|
2204
|
+
}
|
|
2205
|
+
} else {
|
|
2206
|
+
callback( table );
|
|
2207
|
+
}
|
|
2208
|
+
},
|
|
1400
2209
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
2210
|
+
/*
|
|
2211
|
+
██ ██ ██████ ██ ██ ██ ██████ ██ ██████ ▄█████
|
|
2212
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██▄▄ ▀█▄
|
|
2213
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀█▄
|
|
2214
|
+
▀████▀ ██ ██ ██████ ██ ██ ██ ██████ █████▀
|
|
2215
|
+
*/
|
|
2216
|
+
benchmark : function( diff ) {
|
|
2217
|
+
return ( ' (' + ( new Date().getTime() - diff.getTime() ) + ' ms)' );
|
|
2218
|
+
},
|
|
2219
|
+
// deprecated ts.log
|
|
2220
|
+
log : function() {
|
|
2221
|
+
console.log( arguments );
|
|
2222
|
+
},
|
|
2223
|
+
debug : function(c, name) {
|
|
2224
|
+
return c && (
|
|
2225
|
+
c.debug === true ||
|
|
2226
|
+
typeof c.debug === 'string' && c.debug.indexOf(name) > -1
|
|
2227
|
+
);
|
|
2228
|
+
},
|
|
1408
2229
|
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
2230
|
+
// $.isEmptyObject from jQuery v1.4
|
|
2231
|
+
isEmptyObject : function( obj ) {
|
|
2232
|
+
/*jshint forin: false */
|
|
2233
|
+
for ( var name in obj ) {
|
|
2234
|
+
return false;
|
|
2235
|
+
}
|
|
2236
|
+
return true;
|
|
2237
|
+
},
|
|
1413
2238
|
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
if (
|
|
1419
|
-
|
|
1420
|
-
var i, l = a ? a.length : 0, n = mx + num;
|
|
1421
|
-
for (i = 0; i < l; i++) {
|
|
1422
|
-
n += a.charCodeAt(i);
|
|
1423
|
-
}
|
|
1424
|
-
return num * n;
|
|
2239
|
+
isValueInArray : function( column, arry ) {
|
|
2240
|
+
var indx,
|
|
2241
|
+
len = arry && arry.length || 0;
|
|
2242
|
+
for ( indx = 0; indx < len; indx++ ) {
|
|
2243
|
+
if ( arry[ indx ][ 0 ] === column ) {
|
|
2244
|
+
return indx;
|
|
1425
2245
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
ts.sortNumericAsc = function(a, b, num, mx, col, table) {
|
|
1430
|
-
if (a === b) { return 0; }
|
|
1431
|
-
var c = table.config,
|
|
1432
|
-
e = c.string[ (c.empties[col] || c.emptyTo ) ];
|
|
1433
|
-
if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
|
|
1434
|
-
if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
|
|
1435
|
-
if (isNaN(a)) { a = ts.getTextValue(a, num, mx); }
|
|
1436
|
-
if (isNaN(b)) { b = ts.getTextValue(b, num, mx); }
|
|
1437
|
-
return a - b;
|
|
1438
|
-
};
|
|
2246
|
+
}
|
|
2247
|
+
return -1;
|
|
2248
|
+
},
|
|
1439
2249
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
}
|
|
2250
|
+
formatFloat : function( str, table ) {
|
|
2251
|
+
if ( typeof str !== 'string' || str === '' ) { return str; }
|
|
2252
|
+
// allow using formatFloat without a table; defaults to US number format
|
|
2253
|
+
var num,
|
|
2254
|
+
usFormat = table && table.config ? table.config.usNumberFormat !== false :
|
|
2255
|
+
typeof table !== 'undefined' ? table : true;
|
|
2256
|
+
if ( usFormat ) {
|
|
2257
|
+
// US Format - 1,234,567.89 -> 1234567.89
|
|
2258
|
+
str = str.replace( ts.regex.comma, '' );
|
|
2259
|
+
} else {
|
|
2260
|
+
// German Format = 1.234.567,89 -> 1234567.89
|
|
2261
|
+
// French Format = 1 234 567,89 -> 1234567.89
|
|
2262
|
+
str = str.replace( ts.regex.digitNonUS, '' ).replace( ts.regex.comma, '.' );
|
|
2263
|
+
}
|
|
2264
|
+
if ( ts.regex.digitNegativeTest.test( str ) ) {
|
|
2265
|
+
// make (#) into a negative number -> (10) = -10
|
|
2266
|
+
str = str.replace( ts.regex.digitNegativeReplace, '-$1' );
|
|
2267
|
+
}
|
|
2268
|
+
num = parseFloat( str );
|
|
2269
|
+
// return the text instead of zero
|
|
2270
|
+
return isNaN( num ) ? $.trim( str ) : num;
|
|
2271
|
+
},
|
|
1450
2272
|
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
2273
|
+
isDigit : function( str ) {
|
|
2274
|
+
// replace all unwanted chars and match
|
|
2275
|
+
return isNaN( str ) ?
|
|
2276
|
+
ts.regex.digitTest.test( str.toString().replace( ts.regex.digitReplace, '' ) ) :
|
|
2277
|
+
str !== '';
|
|
2278
|
+
},
|
|
1454
2279
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
ts.characterRegexArray[a] = new RegExp('[' + eq[a] + ']', 'g');
|
|
2280
|
+
// computeTableHeaderCellIndexes from:
|
|
2281
|
+
// http://www.javascripttoolbox.com/lib/table/examples.php
|
|
2282
|
+
// http://www.javascripttoolbox.com/temp/table_cellindex.html
|
|
2283
|
+
computeColumnIndex : function( $rows, c ) {
|
|
2284
|
+
var i, j, k, l, cell, cells, rowIndex, rowSpan, colSpan, firstAvailCol,
|
|
2285
|
+
// total columns has been calculated, use it to set the matrixrow
|
|
2286
|
+
columns = c && c.columns || 0,
|
|
2287
|
+
matrix = [],
|
|
2288
|
+
matrixrow = new Array( columns );
|
|
2289
|
+
for ( i = 0; i < $rows.length; i++ ) {
|
|
2290
|
+
cells = $rows[ i ].cells;
|
|
2291
|
+
for ( j = 0; j < cells.length; j++ ) {
|
|
2292
|
+
cell = cells[ j ];
|
|
2293
|
+
rowIndex = i;
|
|
2294
|
+
rowSpan = cell.rowSpan || 1;
|
|
2295
|
+
colSpan = cell.colSpan || 1;
|
|
2296
|
+
if ( typeof matrix[ rowIndex ] === 'undefined' ) {
|
|
2297
|
+
matrix[ rowIndex ] = [];
|
|
2298
|
+
}
|
|
2299
|
+
// Find first available column in the first row
|
|
2300
|
+
for ( k = 0; k < matrix[ rowIndex ].length + 1; k++ ) {
|
|
2301
|
+
if ( typeof matrix[ rowIndex ][ k ] === 'undefined' ) {
|
|
2302
|
+
firstAvailCol = k;
|
|
2303
|
+
break;
|
|
1480
2304
|
}
|
|
1481
2305
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
2306
|
+
// jscs:disable disallowEmptyBlocks
|
|
2307
|
+
if ( columns && cell.cellIndex === firstAvailCol ) {
|
|
2308
|
+
// don't to anything
|
|
2309
|
+
} else if ( cell.setAttribute ) {
|
|
2310
|
+
// jscs:enable disallowEmptyBlocks
|
|
2311
|
+
// add data-column (setAttribute = IE8+)
|
|
2312
|
+
cell.setAttribute( 'data-column', firstAvailCol );
|
|
2313
|
+
} else {
|
|
2314
|
+
// remove once we drop support for IE7 - 1/12/2016
|
|
2315
|
+
$( cell ).attr( 'data-column', firstAvailCol );
|
|
2316
|
+
}
|
|
2317
|
+
for ( k = rowIndex; k < rowIndex + rowSpan; k++ ) {
|
|
2318
|
+
if ( typeof matrix[ k ] === 'undefined' ) {
|
|
2319
|
+
matrix[ k ] = [];
|
|
2320
|
+
}
|
|
2321
|
+
matrixrow = matrix[ k ];
|
|
2322
|
+
for ( l = firstAvailCol; l < firstAvailCol + colSpan; l++ ) {
|
|
2323
|
+
matrixrow[ l ] = 'x';
|
|
1488
2324
|
}
|
|
1489
2325
|
}
|
|
1490
2326
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
2327
|
+
}
|
|
2328
|
+
ts.checkColumnCount($rows, matrix, matrixrow.length);
|
|
2329
|
+
return matrixrow.length;
|
|
2330
|
+
},
|
|
1493
2331
|
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
2332
|
+
checkColumnCount : function($rows, matrix, columns) {
|
|
2333
|
+
// this DOES NOT report any tbody column issues, except for the math and
|
|
2334
|
+
// and column selector widgets
|
|
2335
|
+
var i, len,
|
|
2336
|
+
valid = true,
|
|
2337
|
+
cells = [];
|
|
2338
|
+
for ( i = 0; i < matrix.length; i++ ) {
|
|
2339
|
+
// some matrix entries are undefined when testing the footer because
|
|
2340
|
+
// it is using the rowIndex property
|
|
2341
|
+
if ( matrix[i] ) {
|
|
2342
|
+
len = matrix[i].length;
|
|
2343
|
+
if ( matrix[i].length !== columns ) {
|
|
2344
|
+
valid = false;
|
|
2345
|
+
break;
|
|
1500
2346
|
}
|
|
1501
2347
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
2348
|
+
}
|
|
2349
|
+
if ( !valid ) {
|
|
2350
|
+
$rows.each( function( indx, el ) {
|
|
2351
|
+
var cell = el.parentElement.nodeName;
|
|
2352
|
+
if ( cells.indexOf( cell ) < 0 ) {
|
|
2353
|
+
cells.push( cell );
|
|
2354
|
+
}
|
|
2355
|
+
});
|
|
2356
|
+
console.error(
|
|
2357
|
+
'Invalid or incorrect number of columns in the ' +
|
|
2358
|
+
cells.join( ' or ' ) + '; expected ' + columns +
|
|
2359
|
+
', but found ' + len + ' columns'
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
},
|
|
1504
2363
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
2364
|
+
// automatically add a colgroup with col elements set to a percentage width
|
|
2365
|
+
fixColumnWidth : function( table ) {
|
|
2366
|
+
table = $( table )[ 0 ];
|
|
2367
|
+
var overallWidth, percent, $tbodies, len, index,
|
|
2368
|
+
c = table.config,
|
|
2369
|
+
$colgroup = c.$table.children( 'colgroup' );
|
|
2370
|
+
// remove plugin-added colgroup, in case we need to refresh the widths
|
|
2371
|
+
if ( $colgroup.length && $colgroup.hasClass( ts.css.colgroup ) ) {
|
|
2372
|
+
$colgroup.remove();
|
|
2373
|
+
}
|
|
2374
|
+
if ( c.widthFixed && c.$table.children( 'colgroup' ).length === 0 ) {
|
|
2375
|
+
$colgroup = $( '<colgroup class="' + ts.css.colgroup + '">' );
|
|
2376
|
+
overallWidth = c.$table.width();
|
|
2377
|
+
// only add col for visible columns - fixes #371
|
|
2378
|
+
$tbodies = c.$tbodies.find( 'tr:first' ).children( ':visible' );
|
|
2379
|
+
len = $tbodies.length;
|
|
2380
|
+
for ( index = 0; index < len; index++ ) {
|
|
2381
|
+
percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
|
|
2382
|
+
$colgroup.append( $( '<col>' ).css( 'width', percent ) );
|
|
2383
|
+
}
|
|
2384
|
+
c.$table.prepend( $colgroup );
|
|
2385
|
+
}
|
|
2386
|
+
},
|
|
2387
|
+
|
|
2388
|
+
// get sorter, string, empty, etc options for each column from
|
|
2389
|
+
// jQuery data, metadata, header option or header class name ('sorter-false')
|
|
2390
|
+
// priority = jQuery data > meta > headers option > header class name
|
|
2391
|
+
getData : function( header, configHeader, key ) {
|
|
2392
|
+
var meta, cl4ss,
|
|
2393
|
+
val = '',
|
|
2394
|
+
$header = $( header );
|
|
2395
|
+
if ( !$header.length ) { return ''; }
|
|
2396
|
+
meta = $.metadata ? $header.metadata() : false;
|
|
2397
|
+
cl4ss = ' ' + ( $header.attr( 'class' ) || '' );
|
|
2398
|
+
if ( typeof $header.data( key ) !== 'undefined' ||
|
|
2399
|
+
typeof $header.data( key.toLowerCase() ) !== 'undefined' ) {
|
|
2400
|
+
// 'data-lockedOrder' is assigned to 'lockedorder'; but 'data-locked-order' is assigned to 'lockedOrder'
|
|
2401
|
+
// 'data-sort-initial-order' is assigned to 'sortInitialOrder'
|
|
2402
|
+
val += $header.data( key ) || $header.data( key.toLowerCase() );
|
|
2403
|
+
} else if ( meta && typeof meta[ key ] !== 'undefined' ) {
|
|
2404
|
+
val += meta[ key ];
|
|
2405
|
+
} else if ( configHeader && typeof configHeader[ key ] !== 'undefined' ) {
|
|
2406
|
+
val += configHeader[ key ];
|
|
2407
|
+
} else if ( cl4ss !== ' ' && cl4ss.match( ' ' + key + '-' ) ) {
|
|
2408
|
+
// include sorter class name 'sorter-text', etc; now works with 'sorter-my-custom-parser'
|
|
2409
|
+
val = cl4ss.match( new RegExp( '\\s' + key + '-([\\w-]+)' ) )[ 1 ] || '';
|
|
2410
|
+
}
|
|
2411
|
+
return $.trim( val );
|
|
2412
|
+
},
|
|
2413
|
+
|
|
2414
|
+
getColumnData : function( table, obj, indx, getCell, $headers ) {
|
|
2415
|
+
if ( typeof obj !== 'object' || obj === null ) {
|
|
2416
|
+
return obj;
|
|
2417
|
+
}
|
|
2418
|
+
table = $( table )[ 0 ];
|
|
2419
|
+
var $header, key,
|
|
2420
|
+
c = table.config,
|
|
2421
|
+
$cells = ( $headers || c.$headers ),
|
|
2422
|
+
// c.$headerIndexed is not defined initially
|
|
2423
|
+
$cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||
|
|
2424
|
+
$cells.find( '[data-column="' + indx + '"]:last' );
|
|
2425
|
+
if ( typeof obj[ indx ] !== 'undefined' ) {
|
|
2426
|
+
return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];
|
|
2427
|
+
}
|
|
2428
|
+
for ( key in obj ) {
|
|
2429
|
+
if ( typeof key === 'string' ) {
|
|
2430
|
+
$header = $cell
|
|
2431
|
+
// header cell with class/id
|
|
2432
|
+
.filter( key )
|
|
2433
|
+
// find elements within the header cell with cell/id
|
|
2434
|
+
.add( $cell.find( key ) );
|
|
2435
|
+
if ( $header.length ) {
|
|
2436
|
+
return obj[ key ];
|
|
1510
2437
|
}
|
|
1511
2438
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
};
|
|
2439
|
+
}
|
|
2440
|
+
return;
|
|
2441
|
+
},
|
|
1516
2442
|
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
2443
|
+
// *** Process table ***
|
|
2444
|
+
// add processing indicator
|
|
2445
|
+
isProcessing : function( $table, toggle, $headers ) {
|
|
2446
|
+
$table = $( $table );
|
|
2447
|
+
var c = $table[ 0 ].config,
|
|
2448
|
+
// default to all headers
|
|
2449
|
+
$header = $headers || $table.find( '.' + ts.css.header );
|
|
2450
|
+
if ( toggle ) {
|
|
2451
|
+
// don't use sortList if custom $headers used
|
|
2452
|
+
if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
|
|
2453
|
+
// get headers from the sortList
|
|
2454
|
+
$header = $header.filter( function() {
|
|
2455
|
+
// get data-column from attr to keep compatibility with jQuery 1.2.6
|
|
2456
|
+
return this.sortDisabled ?
|
|
2457
|
+
false :
|
|
2458
|
+
ts.isValueInArray( parseFloat( $( this ).attr( 'data-column' ) ), c.sortList ) >= 0;
|
|
2459
|
+
});
|
|
1525
2460
|
}
|
|
1526
|
-
|
|
1527
|
-
}
|
|
2461
|
+
$table.add( $header ).addClass( ts.css.processing + ' ' + c.cssProcessing );
|
|
2462
|
+
} else {
|
|
2463
|
+
$table.add( $header ).removeClass( ts.css.processing + ' ' + c.cssProcessing );
|
|
2464
|
+
}
|
|
2465
|
+
},
|
|
1528
2466
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
2467
|
+
// detach tbody but save the position
|
|
2468
|
+
// don't use tbody because there are portions that look for a tbody index (updateCell)
|
|
2469
|
+
processTbody : function( table, $tb, getIt ) {
|
|
2470
|
+
table = $( table )[ 0 ];
|
|
2471
|
+
if ( getIt ) {
|
|
2472
|
+
table.isProcessing = true;
|
|
2473
|
+
$tb.before( '<colgroup class="tablesorter-savemyplace"/>' );
|
|
2474
|
+
return $.fn.detach ? $tb.detach() : $tb.remove();
|
|
2475
|
+
}
|
|
2476
|
+
var holdr = $( table ).find( 'colgroup.tablesorter-savemyplace' );
|
|
2477
|
+
$tb.insertAfter( holdr );
|
|
2478
|
+
holdr.remove();
|
|
2479
|
+
table.isProcessing = false;
|
|
2480
|
+
},
|
|
1532
2481
|
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
};
|
|
2482
|
+
clearTableBody : function( table ) {
|
|
2483
|
+
$( table )[ 0 ].config.$tbodies.children().detach();
|
|
2484
|
+
},
|
|
1537
2485
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
2486
|
+
// used when replacing accented characters during sorting
|
|
2487
|
+
characterEquivalents : {
|
|
2488
|
+
'a' : '\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5', // áàâãäąå
|
|
2489
|
+
'A' : '\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5', // ÁÀÂÃÄĄÅ
|
|
2490
|
+
'c' : '\u00e7\u0107\u010d', // çćč
|
|
2491
|
+
'C' : '\u00c7\u0106\u010c', // ÇĆČ
|
|
2492
|
+
'e' : '\u00e9\u00e8\u00ea\u00eb\u011b\u0119', // éèêëěę
|
|
2493
|
+
'E' : '\u00c9\u00c8\u00ca\u00cb\u011a\u0118', // ÉÈÊËĚĘ
|
|
2494
|
+
'i' : '\u00ed\u00ec\u0130\u00ee\u00ef\u0131', // íìİîïı
|
|
2495
|
+
'I' : '\u00cd\u00cc\u0130\u00ce\u00cf', // ÍÌİÎÏ
|
|
2496
|
+
'o' : '\u00f3\u00f2\u00f4\u00f5\u00f6\u014d', // óòôõöō
|
|
2497
|
+
'O' : '\u00d3\u00d2\u00d4\u00d5\u00d6\u014c', // ÓÒÔÕÖŌ
|
|
2498
|
+
'ss': '\u00df', // ß (s sharp)
|
|
2499
|
+
'SS': '\u1e9e', // ẞ (Capital sharp s)
|
|
2500
|
+
'u' : '\u00fa\u00f9\u00fb\u00fc\u016f', // úùûüů
|
|
2501
|
+
'U' : '\u00da\u00d9\u00db\u00dc\u016e' // ÚÙÛÜŮ
|
|
2502
|
+
},
|
|
1547
2503
|
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
// ensure unique widget ids
|
|
1560
|
-
c.widgets = $.grep(c.widgets, function(v, k){
|
|
1561
|
-
return $.inArray(v, c.widgets) === k;
|
|
1562
|
-
});
|
|
1563
|
-
// build widget array & add priority as needed
|
|
1564
|
-
$.each(c.widgets || [], function(i,n){
|
|
1565
|
-
wd = ts.getWidgetById(n);
|
|
1566
|
-
if (wd && wd.id) {
|
|
1567
|
-
// set priority to 10 if not defined
|
|
1568
|
-
if (!wd.priority) { wd.priority = 10; }
|
|
1569
|
-
widgets[i] = wd;
|
|
1570
|
-
}
|
|
1571
|
-
});
|
|
1572
|
-
// sort widgets by priority
|
|
1573
|
-
widgets.sort(function(a, b){
|
|
1574
|
-
return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1;
|
|
1575
|
-
});
|
|
1576
|
-
// add/update selected widgets
|
|
1577
|
-
$.each(widgets, function(i,w){
|
|
1578
|
-
if (w) {
|
|
1579
|
-
if (init || !(c.widgetInit[w.id])) {
|
|
1580
|
-
// set init flag first to prevent calling init more than once (e.g. pager)
|
|
1581
|
-
c.widgetInit[w.id] = true;
|
|
1582
|
-
if (w.hasOwnProperty('options')) {
|
|
1583
|
-
wo = table.config.widgetOptions = $.extend( true, {}, w.options, wo );
|
|
1584
|
-
}
|
|
1585
|
-
if (w.hasOwnProperty('init')) {
|
|
1586
|
-
w.init(table, w, c, wo);
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
if (!init && w.hasOwnProperty('format')) {
|
|
1590
|
-
w.format(table, c, wo, false);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
});
|
|
2504
|
+
replaceAccents : function( str ) {
|
|
2505
|
+
var chr,
|
|
2506
|
+
acc = '[',
|
|
2507
|
+
eq = ts.characterEquivalents;
|
|
2508
|
+
if ( !ts.characterRegex ) {
|
|
2509
|
+
ts.characterRegexArray = {};
|
|
2510
|
+
for ( chr in eq ) {
|
|
2511
|
+
if ( typeof chr === 'string' ) {
|
|
2512
|
+
acc += eq[ chr ];
|
|
2513
|
+
ts.characterRegexArray[ chr ] = new RegExp( '[' + eq[ chr ] + ']', 'g' );
|
|
2514
|
+
}
|
|
1594
2515
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
2516
|
+
ts.characterRegex = new RegExp( acc + ']' );
|
|
2517
|
+
}
|
|
2518
|
+
if ( ts.characterRegex.test( str ) ) {
|
|
2519
|
+
for ( chr in eq ) {
|
|
2520
|
+
if ( typeof chr === 'string' ) {
|
|
2521
|
+
str = str.replace( ts.characterRegexArray[ chr ], chr );
|
|
2522
|
+
}
|
|
1601
2523
|
}
|
|
1602
|
-
}
|
|
2524
|
+
}
|
|
2525
|
+
return str;
|
|
2526
|
+
},
|
|
1603
2527
|
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
2528
|
+
validateOptions : function( c ) {
|
|
2529
|
+
var setting, setting2, typ, timer,
|
|
2530
|
+
// ignore options containing an array
|
|
2531
|
+
ignore = 'headers sortForce sortList sortAppend widgets'.split( ' ' ),
|
|
2532
|
+
orig = c.originalSettings;
|
|
2533
|
+
if ( orig ) {
|
|
2534
|
+
if ( ts.debug(c, 'core') ) {
|
|
2535
|
+
timer = new Date();
|
|
2536
|
+
}
|
|
2537
|
+
for ( setting in orig ) {
|
|
2538
|
+
typ = typeof ts.defaults[setting];
|
|
2539
|
+
if ( typ === 'undefined' ) {
|
|
2540
|
+
console.warn( 'Tablesorter Warning! "table.config.' + setting + '" option not recognized' );
|
|
2541
|
+
} else if ( typ === 'object' ) {
|
|
2542
|
+
for ( setting2 in orig[setting] ) {
|
|
2543
|
+
typ = ts.defaults[setting] && typeof ts.defaults[setting][setting2];
|
|
2544
|
+
if ( $.inArray( setting, ignore ) < 0 && typ === 'undefined' ) {
|
|
2545
|
+
console.warn( 'Tablesorter Warning! "table.config.' + setting + '.' + setting2 + '" option not recognized' );
|
|
2546
|
+
}
|
|
1617
2547
|
}
|
|
1618
2548
|
}
|
|
1619
2549
|
}
|
|
1620
|
-
if (
|
|
1621
|
-
ts.
|
|
2550
|
+
if ( ts.debug(c, 'core') ) {
|
|
2551
|
+
console.log( 'validate options time:' + ts.benchmark( timer ) );
|
|
1622
2552
|
}
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
// get sorter, string, empty, etc options for each column from
|
|
1626
|
-
// jQuery data, metadata, header option or header class name ("sorter-false")
|
|
1627
|
-
// priority = jQuery data > meta > headers option > header class name
|
|
1628
|
-
ts.getData = function(h, ch, key) {
|
|
1629
|
-
var val = '', $h = $(h), m, cl;
|
|
1630
|
-
if (!$h.length) { return ''; }
|
|
1631
|
-
m = $.metadata ? $h.metadata() : false;
|
|
1632
|
-
cl = ' ' + ($h.attr('class') || '');
|
|
1633
|
-
if (typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined'){
|
|
1634
|
-
// "data-lockedOrder" is assigned to "lockedorder"; but "data-locked-order" is assigned to "lockedOrder"
|
|
1635
|
-
// "data-sort-initial-order" is assigned to "sortInitialOrder"
|
|
1636
|
-
val += $h.data(key) || $h.data(key.toLowerCase());
|
|
1637
|
-
} else if (m && typeof m[key] !== 'undefined') {
|
|
1638
|
-
val += m[key];
|
|
1639
|
-
} else if (ch && typeof ch[key] !== 'undefined') {
|
|
1640
|
-
val += ch[key];
|
|
1641
|
-
} else if (cl !== ' ' && cl.match(' ' + key + '-')) {
|
|
1642
|
-
// include sorter class name "sorter-text", etc; now works with "sorter-my-custom-parser"
|
|
1643
|
-
val = cl.match( new RegExp('\\s' + key + '-([\\w-]+)') )[1] || '';
|
|
1644
|
-
}
|
|
1645
|
-
return $.trim(val);
|
|
1646
|
-
};
|
|
2553
|
+
}
|
|
2554
|
+
},
|
|
1647
2555
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
2556
|
+
// restore headers
|
|
2557
|
+
restoreHeaders : function( table ) {
|
|
2558
|
+
var index, $cell,
|
|
2559
|
+
c = $( table )[ 0 ].config,
|
|
2560
|
+
$headers = c.$table.find( c.selectorHeaders ),
|
|
2561
|
+
len = $headers.length;
|
|
2562
|
+
// don't use c.$headers here in case header cells were swapped
|
|
2563
|
+
for ( index = 0; index < len; index++ ) {
|
|
2564
|
+
$cell = $headers.eq( index );
|
|
2565
|
+
// only restore header cells if it is wrapped
|
|
2566
|
+
// because this is also used by the updateAll method
|
|
2567
|
+
if ( $cell.find( '.' + ts.css.headerIn ).length ) {
|
|
2568
|
+
$cell.html( c.headerContent[ index ] );
|
|
1661
2569
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
|
|
1665
|
-
}
|
|
1666
|
-
i = parseFloat(s);
|
|
1667
|
-
// return the text instead of zero
|
|
1668
|
-
return isNaN(i) ? $.trim(s) : i;
|
|
1669
|
-
};
|
|
1670
|
-
|
|
1671
|
-
ts.isDigit = function(s) {
|
|
1672
|
-
// replace all unwanted chars and match
|
|
1673
|
-
return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : true;
|
|
1674
|
-
};
|
|
1675
|
-
|
|
1676
|
-
}()
|
|
1677
|
-
});
|
|
2570
|
+
}
|
|
2571
|
+
},
|
|
1678
2572
|
|
|
1679
|
-
|
|
1680
|
-
|
|
2573
|
+
destroy : function( table, removeClasses, callback ) {
|
|
2574
|
+
table = $( table )[ 0 ];
|
|
2575
|
+
if ( !table.hasInitialized ) { return; }
|
|
2576
|
+
// remove all widgets
|
|
2577
|
+
ts.removeWidget( table, true, false );
|
|
2578
|
+
var events,
|
|
2579
|
+
$t = $( table ),
|
|
2580
|
+
c = table.config,
|
|
2581
|
+
$h = $t.find( 'thead:first' ),
|
|
2582
|
+
$r = $h.find( 'tr.' + ts.css.headerRow ).removeClass( ts.css.headerRow + ' ' + c.cssHeaderRow ),
|
|
2583
|
+
$f = $t.find( 'tfoot:first > tr' ).children( 'th, td' );
|
|
2584
|
+
if ( removeClasses === false && $.inArray( 'uitheme', c.widgets ) >= 0 ) {
|
|
2585
|
+
// reapply uitheme classes, in case we want to maintain appearance
|
|
2586
|
+
$t.triggerHandler( 'applyWidgetId', [ 'uitheme' ] );
|
|
2587
|
+
$t.triggerHandler( 'applyWidgetId', [ 'zebra' ] );
|
|
2588
|
+
}
|
|
2589
|
+
// remove widget added rows, just in case
|
|
2590
|
+
$h.find( 'tr' ).not( $r ).remove();
|
|
2591
|
+
// disable tablesorter - not using .unbind( namespace ) because namespacing was
|
|
2592
|
+
// added in jQuery v1.4.3 - see http://api.jquery.com/event.namespace/
|
|
2593
|
+
events = 'sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton ' +
|
|
2594
|
+
'appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave ' +
|
|
2595
|
+
'keypress sortBegin sortEnd resetToLoadState '.split( ' ' )
|
|
2596
|
+
.join( c.namespace + ' ' );
|
|
2597
|
+
$t
|
|
2598
|
+
.removeData( 'tablesorter' )
|
|
2599
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) );
|
|
2600
|
+
c.$headers
|
|
2601
|
+
.add( $f )
|
|
2602
|
+
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join( ' ' ) )
|
|
2603
|
+
.removeAttr( 'data-column' )
|
|
2604
|
+
.removeAttr( 'aria-label' )
|
|
2605
|
+
.attr( 'aria-disabled', 'true' );
|
|
2606
|
+
$r
|
|
2607
|
+
.find( c.selectorSort )
|
|
2608
|
+
.unbind( ( 'mousedown mouseup keypress '.split( ' ' ).join( c.namespace + ' ' ) ).replace( ts.regex.spaces, ' ' ) );
|
|
2609
|
+
ts.restoreHeaders( table );
|
|
2610
|
+
$t.toggleClass( ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false );
|
|
2611
|
+
$t.removeClass(c.namespace.slice(1));
|
|
2612
|
+
// clear flag in case the plugin is initialized again
|
|
2613
|
+
table.hasInitialized = false;
|
|
2614
|
+
delete table.config.cache;
|
|
2615
|
+
if ( typeof callback === 'function' ) {
|
|
2616
|
+
callback( table );
|
|
2617
|
+
}
|
|
2618
|
+
if ( ts.debug(c, 'core') ) {
|
|
2619
|
+
console.log( 'tablesorter has been removed' );
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
1681
2622
|
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2623
|
+
};
|
|
2624
|
+
|
|
2625
|
+
$.fn.tablesorter = function( settings ) {
|
|
2626
|
+
return this.each( function() {
|
|
2627
|
+
var table = this,
|
|
2628
|
+
// merge & extend config options
|
|
2629
|
+
c = $.extend( true, {}, ts.defaults, settings, ts.instanceMethods );
|
|
2630
|
+
// save initial settings
|
|
2631
|
+
c.originalSettings = settings;
|
|
2632
|
+
// create a table from data (build table widget)
|
|
2633
|
+
if ( !table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE' ) {
|
|
2634
|
+
// return the table (in case the original target is the table's container)
|
|
2635
|
+
ts.buildTable( table, c );
|
|
2636
|
+
} else {
|
|
2637
|
+
ts.setup( table, c );
|
|
2638
|
+
}
|
|
2639
|
+
});
|
|
2640
|
+
};
|
|
2641
|
+
|
|
2642
|
+
// set up debug logs
|
|
2643
|
+
if ( !( window.console && window.console.log ) ) {
|
|
2644
|
+
// access $.tablesorter.logs for browsers that don't have a console...
|
|
2645
|
+
ts.logs = [];
|
|
2646
|
+
/*jshint -W020 */
|
|
2647
|
+
console = {};
|
|
2648
|
+
console.log = console.warn = console.error = console.table = function() {
|
|
2649
|
+
var arg = arguments.length > 1 ? arguments : arguments[0];
|
|
2650
|
+
ts.logs[ ts.logs.length ] = { date: Date.now(), log: arg };
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
1686
2653
|
|
|
1687
2654
|
// add default parsers
|
|
1688
2655
|
ts.addParser({
|
|
1689
|
-
id: 'no-parser',
|
|
1690
|
-
is: function() {
|
|
2656
|
+
id : 'no-parser',
|
|
2657
|
+
is : function() {
|
|
1691
2658
|
return false;
|
|
1692
2659
|
},
|
|
1693
|
-
format: function() {
|
|
2660
|
+
format : function() {
|
|
1694
2661
|
return '';
|
|
1695
2662
|
},
|
|
1696
|
-
type: 'text'
|
|
2663
|
+
type : 'text'
|
|
1697
2664
|
});
|
|
1698
2665
|
|
|
1699
2666
|
ts.addParser({
|
|
1700
|
-
id:
|
|
1701
|
-
is: function() {
|
|
2667
|
+
id : 'text',
|
|
2668
|
+
is : function() {
|
|
1702
2669
|
return true;
|
|
1703
2670
|
},
|
|
1704
|
-
format: function(
|
|
2671
|
+
format : function( str, table ) {
|
|
1705
2672
|
var c = table.config;
|
|
1706
|
-
if (
|
|
1707
|
-
|
|
1708
|
-
|
|
2673
|
+
if ( str ) {
|
|
2674
|
+
str = $.trim( c.ignoreCase ? str.toLocaleLowerCase() : str );
|
|
2675
|
+
str = c.sortLocaleCompare ? ts.replaceAccents( str ) : str;
|
|
1709
2676
|
}
|
|
1710
|
-
return
|
|
2677
|
+
return str;
|
|
1711
2678
|
},
|
|
1712
|
-
type:
|
|
2679
|
+
type : 'text'
|
|
1713
2680
|
});
|
|
1714
2681
|
|
|
2682
|
+
ts.regex.nondigit = /[^\w,. \-()]/g;
|
|
1715
2683
|
ts.addParser({
|
|
1716
|
-
id:
|
|
1717
|
-
is: function(
|
|
1718
|
-
return ts.isDigit(
|
|
2684
|
+
id : 'digit',
|
|
2685
|
+
is : function( str ) {
|
|
2686
|
+
return ts.isDigit( str );
|
|
1719
2687
|
},
|
|
1720
|
-
format: function(
|
|
1721
|
-
var
|
|
1722
|
-
return
|
|
2688
|
+
format : function( str, table ) {
|
|
2689
|
+
var num = ts.formatFloat( ( str || '' ).replace( ts.regex.nondigit, '' ), table );
|
|
2690
|
+
return str && typeof num === 'number' ? num :
|
|
2691
|
+
str ? $.trim( str && table.config.ignoreCase ? str.toLocaleLowerCase() : str ) : str;
|
|
1723
2692
|
},
|
|
1724
|
-
type:
|
|
2693
|
+
type : 'numeric'
|
|
1725
2694
|
});
|
|
1726
2695
|
|
|
2696
|
+
ts.regex.currencyReplace = /[+\-,. ]/g;
|
|
2697
|
+
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
|
1727
2698
|
ts.addParser({
|
|
1728
|
-
id:
|
|
1729
|
-
is: function(
|
|
1730
|
-
|
|
2699
|
+
id : 'currency',
|
|
2700
|
+
is : function( str ) {
|
|
2701
|
+
str = ( str || '' ).replace( ts.regex.currencyReplace, '' );
|
|
2702
|
+
// test for £$€¤¥¢
|
|
2703
|
+
return ts.regex.currencyTest.test( str );
|
|
1731
2704
|
},
|
|
1732
|
-
format: function(
|
|
1733
|
-
var
|
|
1734
|
-
return
|
|
2705
|
+
format : function( str, table ) {
|
|
2706
|
+
var num = ts.formatFloat( ( str || '' ).replace( ts.regex.nondigit, '' ), table );
|
|
2707
|
+
return str && typeof num === 'number' ? num :
|
|
2708
|
+
str ? $.trim( str && table.config.ignoreCase ? str.toLocaleLowerCase() : str ) : str;
|
|
1735
2709
|
},
|
|
1736
|
-
type:
|
|
2710
|
+
type : 'numeric'
|
|
1737
2711
|
});
|
|
1738
2712
|
|
|
2713
|
+
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
|
2714
|
+
// now, this regex can be updated before initialization
|
|
2715
|
+
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
|
2716
|
+
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\/(www\.)?/;
|
|
1739
2717
|
ts.addParser({
|
|
1740
|
-
id:
|
|
1741
|
-
is: function(
|
|
1742
|
-
return
|
|
2718
|
+
id : 'url',
|
|
2719
|
+
is : function( str ) {
|
|
2720
|
+
return ts.regex.urlProtocolTest.test( str );
|
|
1743
2721
|
},
|
|
1744
|
-
format: function(
|
|
1745
|
-
|
|
1746
|
-
r = "",
|
|
1747
|
-
l = a.length;
|
|
1748
|
-
for (i = 0; i < l; i++) {
|
|
1749
|
-
r += ("00" + a[i]).slice(-3);
|
|
1750
|
-
}
|
|
1751
|
-
return s ? ts.formatFloat(r, table) : s;
|
|
2722
|
+
format : function( str ) {
|
|
2723
|
+
return str ? $.trim( str.replace( ts.regex.urlProtocolReplace, '' ) ) : str;
|
|
1752
2724
|
},
|
|
1753
|
-
type:
|
|
2725
|
+
type : 'text'
|
|
1754
2726
|
});
|
|
1755
2727
|
|
|
2728
|
+
ts.regex.dash = /-/g;
|
|
2729
|
+
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
|
1756
2730
|
ts.addParser({
|
|
1757
|
-
id:
|
|
1758
|
-
is: function(
|
|
1759
|
-
return
|
|
2731
|
+
id : 'isoDate',
|
|
2732
|
+
is : function( str ) {
|
|
2733
|
+
return ts.regex.isoDate.test( str );
|
|
1760
2734
|
},
|
|
1761
|
-
format: function(
|
|
1762
|
-
|
|
2735
|
+
format : function( str ) {
|
|
2736
|
+
var date = str ? new Date( str.replace( ts.regex.dash, '/' ) ) : str;
|
|
2737
|
+
return date instanceof Date && isFinite( date ) ? date.getTime() : str;
|
|
1763
2738
|
},
|
|
1764
|
-
type:
|
|
2739
|
+
type : 'numeric'
|
|
1765
2740
|
});
|
|
1766
2741
|
|
|
2742
|
+
ts.regex.percent = /%/g;
|
|
2743
|
+
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
|
1767
2744
|
ts.addParser({
|
|
1768
|
-
id:
|
|
1769
|
-
is: function(
|
|
1770
|
-
return
|
|
2745
|
+
id : 'percent',
|
|
2746
|
+
is : function( str ) {
|
|
2747
|
+
return ts.regex.percentTest.test( str ) && str.length < 15;
|
|
1771
2748
|
},
|
|
1772
|
-
format: function(
|
|
1773
|
-
return
|
|
2749
|
+
format : function( str, table ) {
|
|
2750
|
+
return str ? ts.formatFloat( str.replace( ts.regex.percent, '' ), table ) : str;
|
|
1774
2751
|
},
|
|
1775
|
-
type:
|
|
2752
|
+
type : 'numeric'
|
|
1776
2753
|
});
|
|
1777
2754
|
|
|
2755
|
+
// added image parser to core v2.17.9
|
|
1778
2756
|
ts.addParser({
|
|
1779
|
-
id:
|
|
1780
|
-
is: function(
|
|
1781
|
-
return
|
|
2757
|
+
id : 'image',
|
|
2758
|
+
is : function( str, table, node, $node ) {
|
|
2759
|
+
return $node.find( 'img' ).length > 0;
|
|
1782
2760
|
},
|
|
1783
|
-
format: function(
|
|
1784
|
-
return
|
|
2761
|
+
format : function( str, table, cell ) {
|
|
2762
|
+
return $( cell ).find( 'img' ).attr( table.config.imgAttr || 'alt' ) || str;
|
|
1785
2763
|
},
|
|
1786
|
-
|
|
2764
|
+
parsed : true, // filter widget flag
|
|
2765
|
+
type : 'text'
|
|
1787
2766
|
});
|
|
1788
2767
|
|
|
2768
|
+
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
|
2769
|
+
ts.regex.usLongDateTest1 = /^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i;
|
|
2770
|
+
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
|
1789
2771
|
ts.addParser({
|
|
1790
|
-
id:
|
|
1791
|
-
is: function(
|
|
2772
|
+
id : 'usLongDate',
|
|
2773
|
+
is : function( str ) {
|
|
1792
2774
|
// two digit years are not allowed cross-browser
|
|
1793
2775
|
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
|
1794
|
-
return
|
|
2776
|
+
return ts.regex.usLongDateTest1.test( str ) || ts.regex.usLongDateTest2.test( str );
|
|
1795
2777
|
},
|
|
1796
|
-
format: function(
|
|
1797
|
-
|
|
2778
|
+
format : function( str ) {
|
|
2779
|
+
var date = str ? new Date( str.replace( ts.regex.dateReplace, '$1 $2' ) ) : str;
|
|
2780
|
+
return date instanceof Date && isFinite( date ) ? date.getTime() : str;
|
|
1798
2781
|
},
|
|
1799
|
-
type:
|
|
2782
|
+
type : 'numeric'
|
|
1800
2783
|
});
|
|
1801
2784
|
|
|
2785
|
+
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
|
2786
|
+
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
|
2787
|
+
// escaped "-" because JSHint in Firefox was showing it as an error
|
|
2788
|
+
ts.regex.shortDateReplace = /[\-.,]/g;
|
|
2789
|
+
// XXY covers MDY & DMY formats
|
|
2790
|
+
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
|
2791
|
+
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
|
2792
|
+
ts.convertFormat = function( dateString, format ) {
|
|
2793
|
+
dateString = ( dateString || '' )
|
|
2794
|
+
.replace( ts.regex.spaces, ' ' )
|
|
2795
|
+
.replace( ts.regex.shortDateReplace, '/' );
|
|
2796
|
+
if ( format === 'mmddyyyy' ) {
|
|
2797
|
+
dateString = dateString.replace( ts.regex.shortDateXXY, '$3/$1/$2' );
|
|
2798
|
+
} else if ( format === 'ddmmyyyy' ) {
|
|
2799
|
+
dateString = dateString.replace( ts.regex.shortDateXXY, '$3/$2/$1' );
|
|
2800
|
+
} else if ( format === 'yyyymmdd' ) {
|
|
2801
|
+
dateString = dateString.replace( ts.regex.shortDateYMD, '$1/$2/$3' );
|
|
2802
|
+
}
|
|
2803
|
+
var date = new Date( dateString );
|
|
2804
|
+
return date instanceof Date && isFinite( date ) ? date.getTime() : '';
|
|
2805
|
+
};
|
|
2806
|
+
|
|
1802
2807
|
ts.addParser({
|
|
1803
|
-
id:
|
|
1804
|
-
is: function(
|
|
1805
|
-
|
|
1806
|
-
return
|
|
2808
|
+
id : 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
|
2809
|
+
is : function( str ) {
|
|
2810
|
+
str = ( str || '' ).replace( ts.regex.spaces, ' ' ).replace( ts.regex.shortDateReplace, '/' );
|
|
2811
|
+
return ts.regex.shortDateTest.test( str );
|
|
1807
2812
|
},
|
|
1808
|
-
format: function(
|
|
1809
|
-
if (
|
|
2813
|
+
format : function( str, table, cell, cellIndex ) {
|
|
2814
|
+
if ( str ) {
|
|
1810
2815
|
var c = table.config,
|
|
1811
|
-
|
|
1812
|
-
format =
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
}
|
|
2816
|
+
$header = c.$headerIndexed[ cellIndex ],
|
|
2817
|
+
format = $header.length && $header.data( 'dateFormat' ) ||
|
|
2818
|
+
ts.getData( $header, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat' ) ||
|
|
2819
|
+
c.dateFormat;
|
|
2820
|
+
// save format because getData can be slow...
|
|
2821
|
+
if ( $header.length ) {
|
|
2822
|
+
$header.data( 'dateFormat', format );
|
|
2823
|
+
}
|
|
2824
|
+
return ts.convertFormat( str, format ) || str;
|
|
1821
2825
|
}
|
|
1822
|
-
return
|
|
2826
|
+
return str;
|
|
1823
2827
|
},
|
|
1824
|
-
type:
|
|
2828
|
+
type : 'numeric'
|
|
1825
2829
|
});
|
|
1826
2830
|
|
|
2831
|
+
// match 24 hour time & 12 hours time + am/pm - see http://regexr.com/3c3tk
|
|
2832
|
+
ts.regex.timeTest = /^(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)$|^((?:[01]\d|[2][0-4]):[0-5]\d)$/i;
|
|
2833
|
+
ts.regex.timeMatch = /(0?[1-9]|1[0-2]):([0-5]\d)(\s[AP]M)|((?:[01]\d|[2][0-4]):[0-5]\d)/i;
|
|
1827
2834
|
ts.addParser({
|
|
1828
|
-
id:
|
|
1829
|
-
is: function(
|
|
1830
|
-
return
|
|
2835
|
+
id : 'time',
|
|
2836
|
+
is : function( str ) {
|
|
2837
|
+
return ts.regex.timeTest.test( str );
|
|
1831
2838
|
},
|
|
1832
|
-
format: function(
|
|
1833
|
-
|
|
2839
|
+
format : function( str ) {
|
|
2840
|
+
// isolate time... ignore month, day and year
|
|
2841
|
+
var temp,
|
|
2842
|
+
timePart = ( str || '' ).match( ts.regex.timeMatch ),
|
|
2843
|
+
orig = new Date( str ),
|
|
2844
|
+
// no time component? default to 00:00 by leaving it out, but only if str is defined
|
|
2845
|
+
time = str && ( timePart !== null ? timePart[ 0 ] : '00:00 AM' ),
|
|
2846
|
+
date = time ? new Date( '2000/01/01 ' + time.replace( ts.regex.dateReplace, '$1 $2' ) ) : time;
|
|
2847
|
+
if ( date instanceof Date && isFinite( date ) ) {
|
|
2848
|
+
temp = orig instanceof Date && isFinite( orig ) ? orig.getTime() : 0;
|
|
2849
|
+
// if original string was a valid date, add it to the decimal so the column sorts in some kind of order
|
|
2850
|
+
// luckily new Date() ignores the decimals
|
|
2851
|
+
return temp ? parseFloat( date.getTime() + '.' + orig.getTime() ) : date.getTime();
|
|
2852
|
+
}
|
|
2853
|
+
return str;
|
|
1834
2854
|
},
|
|
1835
|
-
type:
|
|
2855
|
+
type : 'numeric'
|
|
1836
2856
|
});
|
|
1837
2857
|
|
|
1838
2858
|
ts.addParser({
|
|
1839
|
-
id:
|
|
1840
|
-
is: function() {
|
|
2859
|
+
id : 'metadata',
|
|
2860
|
+
is : function() {
|
|
1841
2861
|
return false;
|
|
1842
2862
|
},
|
|
1843
|
-
format: function(
|
|
2863
|
+
format : function( str, table, cell ) {
|
|
1844
2864
|
var c = table.config,
|
|
1845
|
-
p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
|
|
1846
|
-
return $(cell).metadata()[p];
|
|
2865
|
+
p = ( !c.parserMetadataName ) ? 'sortValue' : c.parserMetadataName;
|
|
2866
|
+
return $( cell ).metadata()[ p ];
|
|
1847
2867
|
},
|
|
1848
|
-
type:
|
|
2868
|
+
type : 'numeric'
|
|
1849
2869
|
});
|
|
1850
2870
|
|
|
2871
|
+
/*
|
|
2872
|
+
██████ ██████ █████▄ █████▄ ▄████▄
|
|
2873
|
+
▄█▀ ██▄▄ ██▄▄██ ██▄▄██ ██▄▄██
|
|
2874
|
+
▄█▀ ██▀▀ ██▀▀██ ██▀▀█ ██▀▀██
|
|
2875
|
+
██████ ██████ █████▀ ██ ██ ██ ██
|
|
2876
|
+
*/
|
|
1851
2877
|
// add default widgets
|
|
1852
2878
|
ts.addWidget({
|
|
1853
|
-
id:
|
|
1854
|
-
priority: 90,
|
|
1855
|
-
format: function(table, c, wo) {
|
|
1856
|
-
var $
|
|
1857
|
-
child = new RegExp(c.cssChildRow, 'i'),
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
time = new Date();
|
|
1861
|
-
}
|
|
1862
|
-
for (k = 0; k < b.length; k++ ) {
|
|
2879
|
+
id : 'zebra',
|
|
2880
|
+
priority : 90,
|
|
2881
|
+
format : function( table, c, wo ) {
|
|
2882
|
+
var $visibleRows, $row, count, isEven, tbodyIndex, rowIndex, len,
|
|
2883
|
+
child = new RegExp( c.cssChildRow, 'i' ),
|
|
2884
|
+
$tbodies = c.$tbodies.add( $( c.namespace + '_extra_table' ).children( 'tbody:not(.' + c.cssInfoBlock + ')' ) );
|
|
2885
|
+
for ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
|
1863
2886
|
// loop through the visible rows
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
$
|
|
1869
|
-
//
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
even = (row % 2 === 0);
|
|
1876
|
-
$tr.removeClass(wo.zebra[even ? 1 : 0]).addClass(wo.zebra[even ? 0 : 1]);
|
|
1877
|
-
});
|
|
2887
|
+
count = 0;
|
|
2888
|
+
$visibleRows = $tbodies.eq( tbodyIndex ).children( 'tr:visible' ).not( c.selectorRemove );
|
|
2889
|
+
len = $visibleRows.length;
|
|
2890
|
+
for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
|
|
2891
|
+
$row = $visibleRows.eq( rowIndex );
|
|
2892
|
+
// style child rows the same way the parent row was styled
|
|
2893
|
+
if ( !child.test( $row[ 0 ].className ) ) { count++; }
|
|
2894
|
+
isEven = ( count % 2 === 0 );
|
|
2895
|
+
$row
|
|
2896
|
+
.removeClass( wo.zebra[ isEven ? 1 : 0 ] )
|
|
2897
|
+
.addClass( wo.zebra[ isEven ? 0 : 1 ] );
|
|
1878
2898
|
}
|
|
1879
2899
|
}
|
|
1880
|
-
if (c.debug) {
|
|
1881
|
-
ts.benchmark("Applying Zebra widget", time);
|
|
1882
|
-
}
|
|
1883
2900
|
},
|
|
1884
|
-
remove: function(table, c, wo){
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
$
|
|
1891
|
-
|
|
2901
|
+
remove : function( table, c, wo, refreshing ) {
|
|
2902
|
+
if ( refreshing ) { return; }
|
|
2903
|
+
var tbodyIndex, $tbody,
|
|
2904
|
+
$tbodies = c.$tbodies,
|
|
2905
|
+
toRemove = ( wo.zebra || [ 'even', 'odd' ] ).join( ' ' );
|
|
2906
|
+
for ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
|
2907
|
+
$tbody = ts.processTbody( table, $tbodies.eq( tbodyIndex ), true ); // remove tbody
|
|
2908
|
+
$tbody.children().removeClass( toRemove );
|
|
2909
|
+
ts.processTbody( table, $tbody, false ); // restore tbody
|
|
1892
2910
|
}
|
|
1893
2911
|
}
|
|
1894
2912
|
});
|
|
1895
2913
|
|
|
1896
|
-
})(jQuery);
|
|
2914
|
+
})( jQuery );
|