jquery-tablesorter 1.17.1 → 1.17.2
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +6 -2
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +353 -228
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +41 -37
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +313 -192
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +2 -1
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +63 -48
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +17 -12
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +10 -5
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +114 -71
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +95 -66
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +3 -2
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-repeatheaders.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +120 -59
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +510 -242
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sortTbodies.js +228 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +76 -59
- metadata +3 -2
@@ -54,6 +54,7 @@
|
|
54
54
|
format : function( txt, table, cell, cellIndex ) {
|
55
55
|
var $cell = $( cell ),
|
56
56
|
wo = table.config.widgetOptions,
|
57
|
+
checkedClass = table.config.checkboxClass || 'checked',
|
57
58
|
// returning plain language here because this is what is shown in the
|
58
59
|
// group headers - change it as desired
|
59
60
|
status = wo.group_checkbox ? wo.group_checkbox : [ 'checked', 'unchecked' ],
|
@@ -61,7 +62,7 @@
|
|
61
62
|
isChecked = $input.length ? $input[ 0 ].checked : '';
|
62
63
|
// adding class to row, indicating that a checkbox is checked; includes
|
63
64
|
// a column index in case more than one checkbox happens to be in a row
|
64
|
-
$cell.closest( 'tr' ).toggleClass( '
|
65
|
+
$cell.closest( 'tr' ).toggleClass( checkedClass + ' ' + checkedClass + '-' + cellIndex, isChecked );
|
65
66
|
return $input.length ? status[ isChecked ? 0 : 1 ] : txt;
|
66
67
|
},
|
67
68
|
parsed : true, // filter widget flag
|
@@ -1,75 +1,90 @@
|
|
1
1
|
/*! Parser: metric *//*
|
2
2
|
* Demo: http://jsfiddle.net/Mottie/abkNM/382/
|
3
|
-
* Set the metric name in the header (defaults to
|
4
|
-
* <th data-metric-name="b|byte">HDD Size</th>
|
5
|
-
* <th data-metric-name="m|meter">Distance</th>
|
3
|
+
* Set the metric name in the header (defaults to 'm|meter'), e.g.
|
4
|
+
* <th data-metric-name-abbr="b|B" data-metric-name-full="byte|Byte|BYTE">HDD Size</th>
|
5
|
+
* <th data-metric-name="m|meter">Distance</th> <!-- data-metric-name is deprecated in v2.22.2 -->
|
6
6
|
*/
|
7
7
|
/*jshint jquery:true */
|
8
|
-
;(function($){
|
9
|
-
|
8
|
+
;( function( $ ) {
|
9
|
+
'use strict';
|
10
10
|
|
11
11
|
var prefixes = {
|
12
|
-
//
|
12
|
+
// 'prefix' : [ base 10, base 2 ]
|
13
13
|
// skipping IEEE 1541 defined prefixes: kibibyte, mebibyte, etc, for now.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
'Y|Yotta|yotta' : [ 1e24, Math.pow(1024, 8) ], // 1024^8
|
15
|
+
'Z|Zetta|zetta' : [ 1e21, Math.pow(1024, 7) ], // 1024^7
|
16
|
+
'E|Exa|exa' : [ 1e18, Math.pow(1024, 6) ], // 1024^6
|
17
|
+
'P|Peta|peta' : [ 1e15, Math.pow(1024, 5) ], // 1024^5
|
18
|
+
'T|Tera|tera' : [ 1e12, Math.pow(1024, 4) ], // 1024^4
|
19
|
+
'G|Giga|giga' : [ 1e9, Math.pow(1024, 3) ], // 1024^3
|
20
|
+
'M|Mega|mega' : [ 1e6, Math.pow(1024, 2) ], // 1024^2
|
21
|
+
'k|Kilo|kilo' : [ 1e3, 1024 ], // 1024
|
22
22
|
// prefixes below here are rarely, if ever, used in binary
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
'h|hecto' : [ 1e2, 1e2 ],
|
24
|
+
'da|deka' : [ 1e1, 1e1 ],
|
25
|
+
'd|deci' : [ 1e-1, 1e-1 ],
|
26
|
+
'c|centi' : [ 1e-2, 1e-2],
|
27
|
+
'm|milli' : [ 1e-3, 1e-3 ],
|
28
|
+
'µ|micro' : [ 1e-6, 1e-6 ],
|
29
|
+
'n|nano' : [ 1e-9, 1e-9 ],
|
30
|
+
'p|pico' : [ 1e-12, 1e-12 ],
|
31
|
+
'f|femto' : [ 1e-15, 1e-15 ],
|
32
|
+
'a|atto' : [ 1e-18, 1e-18 ],
|
33
|
+
'z|zepto' : [ 1e-21, 1e-21 ],
|
34
|
+
'y|yocto' : [ 1e-24, 1e-24 ]
|
35
35
|
},
|
36
36
|
// the \\d+ will not catch digits with spaces, commas or decimals; so use the value from n instead
|
37
|
-
RegLong =
|
38
|
-
RegAbbr =
|
37
|
+
RegLong = '(\\d+)(\\s+)?([Zz]etta|[Ee]xa|[Pp]eta|[Tt]era|[Gg]iga|[Mm]ega|kilo|hecto|deka|deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto)(',
|
38
|
+
RegAbbr = '(\\d+)(\\s+)?(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)(',
|
39
|
+
// make these case-insensitive because we all forget the case for these binary values
|
40
|
+
byteTest = /^[b|bit|byte|o|octet]/i;
|
39
41
|
|
40
42
|
$.tablesorter.addParser({
|
41
43
|
id: 'metric',
|
42
44
|
is: function() {
|
43
45
|
return false;
|
44
46
|
},
|
45
|
-
format: function(
|
46
|
-
var
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
format: function(txt, table, cell, cellIndex) {
|
48
|
+
var unit, isBinary, nameLong, nameAbbr,
|
49
|
+
// default base unit name
|
50
|
+
base = 'm|meter',
|
51
|
+
// process number here to get a numerical format (us or eu)
|
52
|
+
num = $.tablesorter.formatFloat( txt.replace(/[^\w,. \-()]/g, ''), table ),
|
53
|
+
$t = table.config.$headerIndexed[ cellIndex ],
|
54
|
+
regex = $t.data( 'metric' );
|
55
|
+
if ( !regex ) {
|
53
56
|
// stored values
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
unit = ( $t.attr('data-metric-name') || base ).split( '|' );
|
58
|
+
nameLong = $t.attr( 'data-metric-name-full' ) || '';
|
59
|
+
nameAbbr = $t.attr( 'data-metric-name-abbr' ) || '';
|
60
|
+
regex = [ nameLong || unit[1] || unit[0].substring(1), nameAbbr || unit[0] ];
|
61
|
+
isBinary = byteTest.test( regex.join( '' ) );
|
62
|
+
// adding 'data-metric-name-full' which would contain 'byte|BYTE|Byte' etc
|
63
|
+
regex[2] = new RegExp( RegLong + (
|
64
|
+
( nameLong === '' ? '' : nameLong + '|' + nameAbbr ) ||
|
65
|
+
// with data-metric-name='b|byte', we end up with 'b|B|byte|BYTE' - maybe not the best solution for case-insensitivity
|
66
|
+
( ( isBinary ? regex[0].toLowerCase() + '|' + regex[0].toUpperCase() : regex[0] ) + '|' +
|
67
|
+
( isBinary ? regex[1].toLowerCase() + '|' + regex[1].toUpperCase() : regex[1] ) ) ) +
|
68
|
+
')' );
|
69
|
+
// adding 'data-metric-name-abbr' which would contain 'b|B' etc
|
70
|
+
regex[3] = new RegExp( RegAbbr + ( nameAbbr ||
|
71
|
+
( ( isBinary ? regex[1].toLowerCase() + '|' + regex[1].toUpperCase() : regex[1] ) ) ) +
|
72
|
+
')' );
|
73
|
+
$t.data( 'metric', regex );
|
59
74
|
}
|
60
75
|
// find match to full name or abbreviation
|
61
|
-
|
62
|
-
if (
|
63
|
-
for (
|
64
|
-
if (
|
76
|
+
unit = txt.match( regex[2] ) || txt.match( regex[3] );
|
77
|
+
if ( unit ) {
|
78
|
+
for ( base in prefixes ) {
|
79
|
+
if ( unit[3].match( base ) ) {
|
65
80
|
// exception when using binary prefix
|
66
81
|
// change base for binary use
|
67
|
-
|
68
|
-
return
|
82
|
+
isBinary = byteTest.test( unit[4] ) ? 1 : 0;
|
83
|
+
return num * prefixes[ base ][ isBinary ];
|
69
84
|
}
|
70
85
|
}
|
71
86
|
}
|
72
|
-
return
|
87
|
+
return num;
|
73
88
|
},
|
74
89
|
type: 'numeric'
|
75
90
|
});
|
@@ -17,7 +17,7 @@ ts.alignChar = {
|
|
17
17
|
column : this.column,
|
18
18
|
align : $this.attr(wo.alignChar_charAttrib),
|
19
19
|
alignIndex : parseInt( $this.attr(wo.alignChar_indexAttrib) || 0, 10),
|
20
|
-
adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0
|
20
|
+
adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0
|
21
21
|
};
|
22
22
|
vars.regex = new RegExp('\\' + vars.align, 'g');
|
23
23
|
if (typeof vars.align !== 'undefined') {
|
@@ -27,8 +27,7 @@ tsColSel = ts.columnSelector = {
|
|
27
27
|
}
|
28
28
|
|
29
29
|
// unique table class name
|
30
|
-
c.
|
31
|
-
c.$table.addClass( c.tableId );
|
30
|
+
c.$table.addClass( c.namespace.slice(1) + 'columnselector' );
|
32
31
|
|
33
32
|
// build column selector/state array
|
34
33
|
colSel = c.selector = { $container : $(wo.columnSelector_container || '<div>') };
|
@@ -205,9 +204,9 @@ tsColSel = ts.columnSelector = {
|
|
205
204
|
},
|
206
205
|
|
207
206
|
updateBreakpoints: function(c, wo) {
|
208
|
-
var priority, column, breaks,
|
207
|
+
var priority, column, breaks, temp,
|
209
208
|
colSel = c.selector,
|
210
|
-
prefix =
|
209
|
+
prefix = c.namespace + 'columnselector',
|
211
210
|
mediaAll = [],
|
212
211
|
breakpts = '';
|
213
212
|
if (wo.columnSelector_mediaquery && !colSel.auto) {
|
@@ -222,9 +221,12 @@ tsColSel = ts.columnSelector = {
|
|
222
221
|
breaks = [];
|
223
222
|
c.$headers.filter('[' + wo.columnSelector_priority + '=' + (priority + 1) + ']').each(function(){
|
224
223
|
column = parseInt($(this).attr('data-column'), 10) + 1;
|
225
|
-
|
226
|
-
breaks.push(prefix +
|
227
|
-
|
224
|
+
temp = ' col:nth-child(' + column + ')';
|
225
|
+
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
226
|
+
temp = ' tr th:nth-child(' + column + ')';
|
227
|
+
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
228
|
+
temp = ' tr td:nth-child(' + column + ')';
|
229
|
+
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
228
230
|
});
|
229
231
|
if (breaks.length) {
|
230
232
|
mediaAll = mediaAll.concat( breaks );
|
@@ -247,16 +249,19 @@ tsColSel = ts.columnSelector = {
|
|
247
249
|
if (wo.columnSelector_mediaquery && c.selector.auto || c.selector.isInitializing) {
|
248
250
|
return;
|
249
251
|
}
|
250
|
-
var column,
|
252
|
+
var column, temp,
|
251
253
|
colSel = c.selector,
|
252
254
|
styles = [],
|
253
|
-
prefix =
|
255
|
+
prefix = c.namespace + 'columnselector';
|
254
256
|
colSel.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){
|
255
257
|
if (!this.checked) {
|
256
258
|
column = parseInt( $(this).attr('data-column'), 10 ) + 1;
|
257
|
-
|
258
|
-
styles.push(prefix +
|
259
|
-
|
259
|
+
temp = ' col:nth-child(' + column + ')';
|
260
|
+
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
261
|
+
temp = ' tr th:nth-child(' + column + ')';
|
262
|
+
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
263
|
+
temp = ' tr td:nth-child(' + column + ')';
|
264
|
+
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
|
260
265
|
}
|
261
266
|
$(this).toggleClass( wo.columnSelector_cssChecked, this.checked );
|
262
267
|
});
|
@@ -13,7 +13,8 @@ var tse = $.tablesorter.editable = {
|
|
13
13
|
lastEdited: 'tseditable-last-edited-cell',
|
14
14
|
|
15
15
|
editComplete: function( c, wo, $cell, refocus ) {
|
16
|
-
|
16
|
+
c.$table
|
17
|
+
.find( '.' + tse.lastEdited )
|
17
18
|
.removeClass( tse.lastEdited )
|
18
19
|
.trigger( wo.editable_editComplete, [ c ] );
|
19
20
|
// restore focus last cell after updating
|
@@ -139,6 +140,7 @@ var tse = $.tablesorter.editable = {
|
|
139
140
|
.on( 'focus' + namespace, '[contenteditable]', function( e ) {
|
140
141
|
clearTimeout( $( this ).data( 'timer' ) );
|
141
142
|
c.$table.data( 'contentFocused', e.target );
|
143
|
+
c.table.isUpdating = true; // prevent sorting while editing
|
142
144
|
var $this = $( this ),
|
143
145
|
selAll = wo.editable_selectAll,
|
144
146
|
column = $this.closest( 'td' ).index(),
|
@@ -150,7 +152,7 @@ var tse = $.tablesorter.editable = {
|
|
150
152
|
$this
|
151
153
|
.off( 'keydown' + namespace )
|
152
154
|
.on( 'keydown' + namespace, function( e ){
|
153
|
-
if ( wo.editable_enterToAccept && e.which === 13 ) {
|
155
|
+
if ( wo.editable_enterToAccept && e.which === 13 && !e.shiftKey ) {
|
154
156
|
e.preventDefault();
|
155
157
|
}
|
156
158
|
});
|
@@ -184,10 +186,11 @@ var tse = $.tablesorter.editable = {
|
|
184
186
|
// user cancelled
|
185
187
|
$this.html( $this.data( 'original' ) ).trigger( 'blur' + namespace );
|
186
188
|
c.$table.data( 'contentFocused', false );
|
189
|
+
c.table.isUpdating = false;
|
187
190
|
return false;
|
188
191
|
}
|
189
192
|
// accept on enter ( if set ), alt-enter ( always ) or if autoAccept is set and element is blurred or unfocused
|
190
|
-
t = e.which === 13 && ( wo.editable_enterToAccept || e.altKey ) || wo.editable_autoAccept && e.type !== 'keydown';
|
193
|
+
t = e.which === 13 && !e.shiftKey && ( wo.editable_enterToAccept || e.altKey ) || wo.editable_autoAccept && e.type !== 'keydown';
|
191
194
|
// change if new or user hits enter ( if option set )
|
192
195
|
if ( t && $this.data( 'before' ) !== txt ) {
|
193
196
|
|
@@ -212,11 +215,11 @@ var tse = $.tablesorter.editable = {
|
|
212
215
|
if ( wo.editable_autoResort ) {
|
213
216
|
setTimeout( function() {
|
214
217
|
c.$table.trigger( 'sorton', [ c.sortList, function() {
|
215
|
-
tse.editComplete( c, wo, c.$table.
|
218
|
+
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ), true );
|
216
219
|
}, true ] );
|
217
220
|
}, 10 );
|
218
221
|
} else {
|
219
|
-
tse.editComplete( c, wo, c.$table.
|
222
|
+
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ) );
|
220
223
|
}
|
221
224
|
} ] );
|
222
225
|
return false;
|
@@ -224,6 +227,8 @@ var tse = $.tablesorter.editable = {
|
|
224
227
|
} else if ( !valid && e.type !== 'keydown' ) {
|
225
228
|
clearTimeout( $this.data( 'timer' ) );
|
226
229
|
$this.data( 'timer', setTimeout( function() {
|
230
|
+
c.table.isUpdating = false; // clear flag or sorting will be disabled
|
231
|
+
|
227
232
|
if ( $.isFunction( wo.editable_blur ) ) {
|
228
233
|
txt = $this.html();
|
229
234
|
wo.editable_blur( wo.editable_trimContent ? $.trim( txt ) : txt, column, $this );
|
@@ -103,6 +103,66 @@ ts.filter = {
|
|
103
103
|
// data.index = column index; table = table element ( DOM )
|
104
104
|
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
105
105
|
types: {
|
106
|
+
or : function( c, data, vars ) {
|
107
|
+
if ( /\|/.test( data.iFilter ) || ts.filter.regex.orSplit.test( data.filter ) ) {
|
108
|
+
var indx, filterMatched, txt, query, regex,
|
109
|
+
// duplicate data but split filter
|
110
|
+
data2 = $.extend( {}, data ),
|
111
|
+
index = data.index,
|
112
|
+
parsed = data.parsed[ index ],
|
113
|
+
filter = data.filter.split( ts.filter.regex.orSplit ),
|
114
|
+
iFilter = data.iFilter.split( ts.filter.regex.orSplit ),
|
115
|
+
len = filter.length;
|
116
|
+
for ( indx = 0; indx < len; indx++ ) {
|
117
|
+
data2.nestedFilters = true;
|
118
|
+
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
119
|
+
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
120
|
+
query = '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
121
|
+
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
122
|
+
// filterMatched = data2.filter === '' && indx > 0 ? true
|
123
|
+
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
124
|
+
filterMatched = regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars );
|
125
|
+
if ( filterMatched ) {
|
126
|
+
return filterMatched;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
// may be null from processing types
|
130
|
+
return filterMatched || false;
|
131
|
+
}
|
132
|
+
return null;
|
133
|
+
},
|
134
|
+
// Look for an AND or && operator ( logical and )
|
135
|
+
and : function( c, data, vars ) {
|
136
|
+
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
137
|
+
var indx, filterMatched, result, txt, query, regex,
|
138
|
+
// duplicate data but split filter
|
139
|
+
data2 = $.extend( {}, data ),
|
140
|
+
index = data.index,
|
141
|
+
parsed = data.parsed[ index ],
|
142
|
+
filter = data.filter.split( ts.filter.regex.andSplit ),
|
143
|
+
iFilter = data.iFilter.split( ts.filter.regex.andSplit ),
|
144
|
+
len = filter.length;
|
145
|
+
for ( indx = 0; indx < len; indx++ ) {
|
146
|
+
data2.nestedFilters = true;
|
147
|
+
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
148
|
+
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
149
|
+
query = ( '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
150
|
+
// replace wild cards since /(a*)/i will match anything
|
151
|
+
.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' );
|
152
|
+
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
153
|
+
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
154
|
+
result = ( regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars ) );
|
155
|
+
if ( indx === 0 ) {
|
156
|
+
filterMatched = result;
|
157
|
+
} else {
|
158
|
+
filterMatched = filterMatched && result;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
// may be null from processing types
|
162
|
+
return filterMatched || false;
|
163
|
+
}
|
164
|
+
return null;
|
165
|
+
},
|
106
166
|
// Look for regex
|
107
167
|
regex: function( c, data ) {
|
108
168
|
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
@@ -190,23 +250,6 @@ ts.filter = {
|
|
190
250
|
}
|
191
251
|
return null;
|
192
252
|
},
|
193
|
-
// Look for an AND or && operator ( logical and )
|
194
|
-
and : function( c, data ) {
|
195
|
-
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
196
|
-
var index = data.index,
|
197
|
-
parsed = data.parsed[index],
|
198
|
-
query = data.iFilter.split( ts.filter.regex.andSplit ),
|
199
|
-
result = data.iExact.search( $.trim( ts.filter.parseFilter( c, query[0], index, parsed ) ) ) >= 0,
|
200
|
-
indx = query.length - 1;
|
201
|
-
while ( result && indx ) {
|
202
|
-
result = result &&
|
203
|
-
data.iExact.search( $.trim( ts.filter.parseFilter( c, query[indx], index, parsed ) ) ) >= 0;
|
204
|
-
indx--;
|
205
|
-
}
|
206
|
-
return result;
|
207
|
-
}
|
208
|
-
return null;
|
209
|
-
},
|
210
253
|
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
211
254
|
range : function( c, data ) {
|
212
255
|
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
@@ -243,24 +286,20 @@ ts.filter = {
|
|
243
286
|
},
|
244
287
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
245
288
|
wild : function( c, data ) {
|
246
|
-
if ( /[\?\*\|]/.test( data.iFilter )
|
289
|
+
if ( /[\?\*\|]/.test( data.iFilter ) ) {
|
247
290
|
var index = data.index,
|
248
291
|
parsed = data.parsed[ index ],
|
249
|
-
|
250
|
-
query = '' + ( ts.filter.parseFilter( c, txt, index, parsed ) || '' );
|
292
|
+
query = '' + ( ts.filter.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
251
293
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
252
|
-
if (
|
253
|
-
|
254
|
-
if ( query[ query.length - 1 ] === '|' ) {
|
255
|
-
query += '*';
|
256
|
-
}
|
257
|
-
query = data.anyMatch && $.isArray( data.rowArray ) ?
|
258
|
-
'(' + query + ')' :
|
259
|
-
'^(' + query + ')$';
|
294
|
+
if ( !/\?\*/.test( query ) && data.nestedFilters ) {
|
295
|
+
query = data.isMatch ? query : '^(' + query + ')$';
|
260
296
|
}
|
261
297
|
// parsing the filter may not work properly when using wildcards =/
|
262
|
-
return new RegExp(
|
263
|
-
.
|
298
|
+
return new RegExp(
|
299
|
+
query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ),
|
300
|
+
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
301
|
+
)
|
302
|
+
.test( data.exact );
|
264
303
|
}
|
265
304
|
return null;
|
266
305
|
},
|
@@ -314,7 +353,7 @@ ts.filter = {
|
|
314
353
|
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)' ,'gi' ),
|
315
354
|
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
316
355
|
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
317
|
-
|
356
|
+
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
318
357
|
iQuery : new RegExp( val, 'i' ),
|
319
358
|
igQuery : new RegExp( val, 'ig' )
|
320
359
|
});
|
@@ -534,7 +573,6 @@ ts.filter = {
|
|
534
573
|
}
|
535
574
|
}
|
536
575
|
},
|
537
|
-
|
538
576
|
setDefaults: function( table, c, wo ) {
|
539
577
|
var isArray, saved, indx, col, $filters,
|
540
578
|
// get current ( default ) filters
|
@@ -761,14 +799,13 @@ ts.filter = {
|
|
761
799
|
}
|
762
800
|
},
|
763
801
|
hideFilters: function( table, c ) {
|
764
|
-
var
|
765
|
-
|
802
|
+
var timer;
|
803
|
+
c.$table
|
766
804
|
.find( '.' + tscss.filterRow )
|
767
|
-
.addClass( tscss.filterRowHide )
|
768
805
|
.bind( 'mouseenter mouseleave', function( e ) {
|
769
806
|
// save event object - http://bugs.jquery.com/ticket/12140
|
770
|
-
var event = e
|
771
|
-
|
807
|
+
var event = e,
|
808
|
+
$filterRow = $( this );
|
772
809
|
clearTimeout( timer );
|
773
810
|
timer = setTimeout( function() {
|
774
811
|
if ( /enter|over/.test( event.type ) ) {
|
@@ -786,13 +823,14 @@ ts.filter = {
|
|
786
823
|
}, 200 );
|
787
824
|
})
|
788
825
|
.find( 'input, select' ).bind( 'focus blur', function( e ) {
|
789
|
-
|
826
|
+
var event = e,
|
827
|
+
$row = $( this ).closest( 'tr' );
|
790
828
|
clearTimeout( timer );
|
791
|
-
var event = e;
|
792
829
|
timer = setTimeout( function() {
|
830
|
+
clearTimeout( timer );
|
793
831
|
// don't hide row if any filter has a value
|
794
832
|
if ( ts.getFilters( c.$table ).join( '' ) === '' ) {
|
795
|
-
$
|
833
|
+
$row.toggleClass( tscss.filterRowHide, event.type !== 'focus' );
|
796
834
|
}
|
797
835
|
}, 200 );
|
798
836
|
});
|
@@ -826,7 +864,7 @@ ts.filter = {
|
|
826
864
|
return $( b ).attr( 'data-lastSearchTime' ) - $( a ).attr( 'data-lastSearchTime' );
|
827
865
|
});
|
828
866
|
}
|
829
|
-
return $();
|
867
|
+
return $input || $();
|
830
868
|
},
|
831
869
|
multipleColumns: function( c, $input ) {
|
832
870
|
// look for multiple columns '1-3,4-6,8' in data-column
|
@@ -879,8 +917,22 @@ ts.filter = {
|
|
879
917
|
}
|
880
918
|
return columns;
|
881
919
|
},
|
920
|
+
processTypes: function( c, data, vars ) {
|
921
|
+
var ffxn,
|
922
|
+
filterMatched = null,
|
923
|
+
matches = null;
|
924
|
+
for ( ffxn in ts.filter.types ) {
|
925
|
+
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
926
|
+
matches = ts.filter.types[ffxn]( c, data, vars );
|
927
|
+
if ( matches !== null ) {
|
928
|
+
filterMatched = matches;
|
929
|
+
}
|
930
|
+
}
|
931
|
+
}
|
932
|
+
return filterMatched;
|
933
|
+
},
|
882
934
|
processRow: function( c, data, vars ) {
|
883
|
-
var
|
935
|
+
var columnIndex, hasSelect, result, val, filterMatched,
|
884
936
|
fxn, ffxn, txt,
|
885
937
|
regex = ts.filter.regex,
|
886
938
|
wo = c.widgetOptions,
|
@@ -891,6 +943,7 @@ ts.filter = {
|
|
891
943
|
// look for multiple columns '1-3,4-6,8'
|
892
944
|
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
893
945
|
data.anyMatch = true;
|
946
|
+
data.isMatch = true;
|
894
947
|
data.rowArray = data.$cells.map( function( i ) {
|
895
948
|
if ( $.inArray( i, columnIndex ) > -1 ) {
|
896
949
|
if ( data.parsed[ i ] ) {
|
@@ -910,16 +963,10 @@ ts.filter = {
|
|
910
963
|
data.exact = data.rowArray.join( ' ' );
|
911
964
|
data.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;
|
912
965
|
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
matches = ts.filter.types[ffxn]( c, data );
|
918
|
-
if ( matches !== null ) {
|
919
|
-
filterMatched = matches;
|
920
|
-
}
|
921
|
-
}
|
922
|
-
}
|
966
|
+
|
967
|
+
vars.excludeMatch = vars.noAnyMatch;
|
968
|
+
filterMatched = ts.filter.processTypes( c, data, vars );
|
969
|
+
|
923
970
|
if ( filterMatched !== null ) {
|
924
971
|
showRow = filterMatched;
|
925
972
|
} else {
|
@@ -946,7 +993,7 @@ ts.filter = {
|
|
946
993
|
data.index = columnIndex;
|
947
994
|
|
948
995
|
// filter types to exclude, per column
|
949
|
-
excludeMatch = vars.excludeFilter[ columnIndex ];
|
996
|
+
vars.excludeMatch = vars.excludeFilter[ columnIndex ];
|
950
997
|
|
951
998
|
// ignore if filter is empty or disabled
|
952
999
|
if ( data.filter ) {
|
@@ -960,6 +1007,9 @@ ts.filter = {
|
|
960
1007
|
}
|
961
1008
|
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
|
962
1009
|
data.exact.toLowerCase() : data.exact;
|
1010
|
+
|
1011
|
+
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
|
1012
|
+
|
963
1013
|
result = showRow; // if showRow is true, show that row
|
964
1014
|
|
965
1015
|
// in case select filter option has a different value vs text 'a - z|A through Z'
|
@@ -984,13 +1034,12 @@ ts.filter = {
|
|
984
1034
|
// data.filter = case sensitive
|
985
1035
|
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
|
986
1036
|
fxn = vars.functions[ columnIndex ];
|
987
|
-
|
988
|
-
hasSelect = $cell.hasClass( 'filter-select' );
|
1037
|
+
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
|
989
1038
|
filterMatched = null;
|
990
1039
|
if ( fxn || ( hasSelect && val ) ) {
|
991
1040
|
if ( fxn === true || hasSelect ) {
|
992
1041
|
// default selector uses exact match unless 'filter-match' class is found
|
993
|
-
filterMatched =
|
1042
|
+
filterMatched = data.isMatch ?
|
994
1043
|
data.iExact.search( data.iFilter ) >= 0 :
|
995
1044
|
data.filter === data.exact;
|
996
1045
|
} else if ( typeof fxn === 'function' ) {
|
@@ -1007,15 +1056,7 @@ ts.filter = {
|
|
1007
1056
|
if ( filterMatched === null ) {
|
1008
1057
|
// cycle through the different filters
|
1009
1058
|
// filters return a boolean or null if nothing matches
|
1010
|
-
|
1011
|
-
for ( ffxn in ts.filter.types ) {
|
1012
|
-
if ( $.inArray( ffxn, excludeMatch ) < 0 && matches === null ) {
|
1013
|
-
matches = ts.filter.types[ ffxn ]( c, data );
|
1014
|
-
if ( matches !== null ) {
|
1015
|
-
filterMatched = matches;
|
1016
|
-
}
|
1017
|
-
}
|
1018
|
-
}
|
1059
|
+
filterMatched = ts.filter.processTypes( c, data, vars );
|
1019
1060
|
if ( filterMatched !== null ) {
|
1020
1061
|
result = filterMatched;
|
1021
1062
|
// Look for match, and add child row data for matching
|
@@ -1049,7 +1090,7 @@ ts.filter = {
|
|
1049
1090
|
anyMatch: false,
|
1050
1091
|
filters: filters,
|
1051
1092
|
// regex filter type cache
|
1052
|
-
filter_regexCache : []
|
1093
|
+
filter_regexCache : []
|
1053
1094
|
},
|
1054
1095
|
vars = {
|
1055
1096
|
// anyMatch really screws up with these types of filters
|
@@ -1270,7 +1311,7 @@ ts.filter = {
|
|
1270
1311
|
},
|
1271
1312
|
getOptionSource: function( table, column, onlyAvail ) {
|
1272
1313
|
table = $( table )[0];
|
1273
|
-
var cts, indx, len,
|
1314
|
+
var cts, txt, indx, len,
|
1274
1315
|
c = table.config,
|
1275
1316
|
wo = c.widgetOptions,
|
1276
1317
|
parsed = [],
|
@@ -1315,11 +1356,13 @@ ts.filter = {
|
|
1315
1356
|
len = arry.length;
|
1316
1357
|
// parse select option values
|
1317
1358
|
for ( indx = 0; indx < len; indx++ ) {
|
1359
|
+
txt = arry[ indx ];
|
1318
1360
|
// parse array data using set column parser; this DOES NOT pass the original
|
1319
1361
|
// table cell to the parser format function
|
1320
1362
|
parsed.push({
|
1321
|
-
t :
|
1322
|
-
|
1363
|
+
t : txt,
|
1364
|
+
// check parser length - fixes #934
|
1365
|
+
p : c.parsers && c.parsers.length && c.parsers[ column ].format( txt, table, [], column ) || txt
|
1323
1366
|
});
|
1324
1367
|
}
|
1325
1368
|
|
@@ -1509,8 +1552,8 @@ ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
|
|
1509
1552
|
$column = ts.filter.getLatestSearch( $column );
|
1510
1553
|
if ( $.isArray( setFilters ) ) {
|
1511
1554
|
// skip first ( latest input ) to maintain cursor position while typing
|
1512
|
-
if ( skipFirst ) {
|
1513
|
-
$column.slice( 1 );
|
1555
|
+
if ( skipFirst && $column.length > 1 ) {
|
1556
|
+
$column = $column.slice( 1 );
|
1514
1557
|
}
|
1515
1558
|
if ( i === c.columns ) {
|
1516
1559
|
// prevent data-column='all' from filling data-column='0,1' ( etc )
|