Subversion Repositories munaweb

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*! Parser: input & select - updated 2018-07-10 (v2.30.7) *//*
2
 * for jQuery 1.7+ & tablesorter 2.7.11+
3
 * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
4
 */
5
/*jshint browser: true, jquery:true, unused:false */
6
;( function( $ ) {
7
	'use strict';
8
 
9
	var updateServer = function( /* event, $table, $input */ ) {
10
		// do something here to update your server, if needed
11
		// event = change event object
12
		// $table = jQuery object of the table that was just updated
13
		// $input = jQuery object(s) of the input or select that was modified; in v2.24.6,
14
		//   if the thead has a checkbox, $input may include multiple elements
15
	};
16
 
17
	// Custom parser for parsing input values
18
	// updated dynamically using the 'change' function below
19
	$.tablesorter.addParser({
20
		id : 'inputs',
21
		is : function() {
22
			return false;
23
		},
24
		format : function( txt, table, cell ) {
25
			var $input = $( cell ).find( 'input' );
26
			return $input.length ? $input.val() : txt;
27
		},
28
		parsed : true, // filter widget flag
29
		type : 'text'
30
	});
31
 
32
	$.tablesorter.addParser({
33
		id : 'inputs-numeric',
34
		is : function() {
35
			return false;
36
		},
37
		format : function( txt, table, cell ) {
38
			var $input = $( cell ).find( 'input' );
39
			var val = $input.length ? $input.val() : txt,
40
				num = $.tablesorter.formatFloat( ( val || '' ).replace( /[^\w,. \-()]/g, '' ), table );
41
			return txt && typeof num === 'number' ? num :
42
				txt ? $.trim( txt && table.config.ignoreCase ? txt.toLocaleLowerCase() : txt ) : txt;
43
		},
44
		parsed : true, // filter widget flag
45
		type : 'numeric'
46
	});
47
 
48
	// Custom parser for including checkbox status if using the grouping widget
49
	// updated dynamically using the 'change' function below
50
	$.tablesorter.addParser({
51
		id : 'checkbox',
52
		is : function() {
53
			return false;
54
		},
55
		format : function( txt, table, cell ) {
56
			var $cell = $( cell ),
57
				wo = table.config.widgetOptions,
58
				// returning plain language here because this is what is shown in the
59
				// group headers - change it as desired
60
				status = wo.group_checkbox ? wo.group_checkbox : [ 'checked', 'unchecked' ],
61
				$input = $cell.find( 'input[type="checkbox"]' ),
62
				isChecked = $input.length ? $input[ 0 ].checked : '';
63
			return $input.length ? status[ isChecked ? 0 : 1 ] : txt;
64
		},
65
		parsed : true, // filter widget flag
66
		type : 'text'
67
	});
68
 
69
	$.tablesorter.addParser({
70
		id: 'radio',
71
		is: function() {
72
			return false;
73
		},
74
		format: function(txt, table, cell) {
75
			var $input = $(cell).find('input:checked');
76
			return $input.length ? $input.val() : txt;
77
		},
78
		parsed: true,
79
		type: 'text'
80
	});
81
 
82
	// Custom parser which returns the currently selected options
83
	// updated dynamically using the 'change' function below
84
	$.tablesorter.addParser({
85
		id : 'select',
86
		is : function() {
87
			return false;
88
		},
89
		format : function( txt, table, cell ) {
90
			var $select = $( cell ).find( 'select' );
91
			return $select.length ? $select.val() : txt;
92
		},
93
		parsed : true, // filter widget flag
94
		type : 'text'
95
	});
96
 
97
	// Select parser to get the selected text
98
	$.tablesorter.addParser({
99
		id : 'select-text',
100
		is : function() {
101
			return false;
102
		},
103
		format : function( txt, table, cell ) {
104
			var $select = $( cell ).find( 'select' );
105
			return $select.length ? $select.find( 'option:selected' ).text() || '' : txt;
106
		},
107
		parsed : true, // filter widget flag
108
		type : 'text'
109
	});
110
 
111
	// Custom parser for parsing textarea values
112
	// updated dynamically using the 'change' function below
113
	$.tablesorter.addParser({
114
		id : 'textarea',
115
		is : function() {
116
			return false;
117
		},
118
		format : function( txt, table, cell ) {
119
			var $textarea = $( cell ).find( 'textarea' );
120
			return $textarea.length ? $textarea.val() : txt;
121
		},
122
		parsed : true, // filter widget flag
123
		type : 'text'
124
	});
125
 
126
	// update defaults for validator; values must be falsy
127
	$.tablesorter.defaults.checkboxClass = '';
128
	$.tablesorter.defaults.checkboxVisible = '';
129
 
130
	// update select and all input types in the tablesorter cache when the change event fires.
131
	// This method only works with jQuery 1.7+
132
	// you can change it to use delegate (v1.4.3+) or live (v1.3+) as desired
133
	// if this code interferes somehow, target the specific table $('#mytable'), instead of $('table')
134
	$( function() {
135
		if ( !$.fn.on ) { return; }
136
		var toggleRowClass = function( $row, checkboxClass, indx, isChecked ) {
137
			// adding class to row, indicating that a checkbox is checked; includes
138
			// a column index in case more than one checkbox happens to be in a row
139
			$row.toggleClass( checkboxClass + '-' + indx, isChecked );
140
			// don't remove checked class if other columns have a check
141
			if ( ( $row[0].className || '' ).match( checkboxClass + '-' ) ) {
142
				$row.addClass( checkboxClass );
143
			} else {
144
				$row.removeClass( checkboxClass );
145
			}
146
		},
147
		updateCheckbox = function($el, state) {
148
			if ($el.length && $el[0].nodeName !== 'INPUT') {
149
				$el = $el.find( 'input[type="checkbox"]' );
150
			}
151
			if ($el.length) {
152
				var ua = window.navigator.userAgent;
153
				if (state === 'indeterminate') {
154
					// needed for IE
155
					$el.prop('checked', !(ua.indexOf('Trident/') > -1 || ua.indexOf('Edge/') > -1));
156
					$el.prop('indeterminate', true);
157
				} else {
158
					$el.prop('checked', state);
159
					$el.prop('indeterminate', false);
160
				}
161
			}
162
		},
163
		updateHeaderCheckbox = function( $table, checkboxClass ) {
164
			var $sticky,
165
				$rows = $table.children( 'tbody' ).children( ':visible' ), // (include child rows?)
166
				len = $rows.length,
167
				c = $table[0].config,
168
				wo = c && c.widgetOptions,
169
				$headers = c && c.$headers.add( $( c.namespace + '_extra_headers' ) ) || $table.children( 'thead' ),
170
				hasSticky = wo && wo.$sticky;
171
			// set indeterminate state on header checkbox
172
			$headers.find( 'input[type="checkbox"]' ).each( function() {
173
				if (hasSticky) {
174
					$sticky = hasSticky.find( '[data-column="' + column + '"]' );
175
				}
176
				var column = $( this ).closest( 'td, th' ).attr( 'data-column' ),
177
					vis = $rows.filter( '.' + checkboxClass + '-' + column ).length,
178
					allChecked = vis === len && len > 0;
179
				if ( vis === 0 || allChecked ) {
180
					updateCheckbox($(this), allChecked);
181
					if ($sticky) {
182
						updateCheckbox($sticky, allChecked);
183
					}
184
				} else {
185
					updateCheckbox($(this), 'indeterminate');
186
					if ($sticky) {
187
						updateCheckbox($sticky, 'indeterminate');
188
					}
189
				}
190
			});
191
 
192
		};
193
 
194
		$( 'table' ).on( 'tablesorter-initialized updateComplete', function() {
195
			this.tablesorterBusy = false;
196
			var namespace = '.parser-forms';
197
			$( this )
198
			// add namespace to table in case of version mismatch (v2.28.10)
199
			.addClass( this.config.namespace.slice(1) )
200
			.children( 'tbody' )
201
			.off( namespace )
202
			.on( 'mouseleave' + namespace, function( event ) {
203
				// make sure we restore original values (trigger blur)
204
				// isTbody is needed to prevent the select from closing in IE
205
				// see https://connect.microsoft.com/IE/feedbackdetail/view/962618/
206
				if ( event.target.nodeName === 'TBODY' ) {
207
					$( ':focus' ).blur();
208
				}
209
			})
210
			.on( 'focus' + namespace, 'select, input:not([type=checkbox]), textarea', function( event ) {
211
				var $row = $( event.target ).closest( 'tr' ),
212
					c = $row.closest( 'table' )[0].config;
213
				if ( !c || c && c.ignoreChildRow && $row.hasClass( c.cssChildRow ) ) {
214
					return;
215
				}
216
				$( this ).data( 'ts-original-value', this.value );
217
			})
218
			.on( 'blur' + namespace, 'input:not([type=checkbox]), textarea', function( event ) {
219
				var $row = $( event.target ).closest( 'tr' ),
220
					c = $row.closest( 'table' )[0].config;
221
				if ( !c || c && c.ignoreChildRow && $row.hasClass( c.cssChildRow ) ) {
222
					return;
223
				}
224
				// restore input value;
225
				// 'change' is triggered before 'blur' so this doesn't replace the new update with the original
226
				this.value = $( this ).data( 'ts-original-value' );
227
			})
228
			.on( 'change keyup '.split( ' ' ).join( namespace + ' ' ), 'select, input, textarea', function( event ) {
229
				var $row = $( this ).closest( 'tr' ),
230
					c = $row.closest( 'table' )[0].config;
231
				if ( !c || c && c.ignoreChildRow && $row.hasClass( c.cssChildRow ) ) {
232
					return;
233
				}
234
				if ( event.which === 27 && !( this.nodeName === 'INPUT' && this.type === 'checkbox' ) ) {
235
					// escape: restore original value
236
					this.value = $( this ).data( 'ts-original-value' );
237
					return;
238
				}
239
				// Update cell cache using... select: change, input: enter or textarea: alt + enter
240
				if ( event.type === 'change' ||
241
					( event.type === 'keyup' && event.which === 13 &&
242
					( event.target.nodeName === 'INPUT' || event.target.nodeName === 'TEXTAREA' && event.altKey ) ) ) {
243
					var undef, checkboxClass,
244
						$target = $( event.target ),
245
						isCheckbox = event.target.type === 'checkbox',
246
						$cell = $target.closest( 'td' ),
247
						indx = $cell[ 0 ].cellIndex,
248
						busy = c.table.tablesorterBusy,
249
						$hdr = c.$headerIndexed && c.$headerIndexed[ indx ] || [],
250
						val = isCheckbox ? event.target.checked : $target.val();
251
					// abort if not a tablesorter table, or busy
252
					if ( $.isEmptyObject( c ) || busy !== false ) {
253
						return;
254
					}
255
					if ( isCheckbox ) {
256
						checkboxClass = c.checkboxClass || 'checked';
257
						toggleRowClass( $cell.closest( 'tr' ), checkboxClass, indx, val );
258
						updateHeaderCheckbox( c.$table, checkboxClass );
259
					}
260
					// don't use updateCell if column is set to 'sorter-false' and 'filter-false',
261
					// or column is set to 'parser-false'
262
					if ( $hdr.length && ( $hdr.hasClass( 'parser-false' ) ||
263
						( $hdr.hasClass( 'sorter-false' ) && $hdr.hasClass( 'filter-false' ) ) ) ||
264
						// table already updating; get out of here, we might be in an endless loop (in IE)! See #971
265
						( event.type === 'change' && c.table.isUpdating ) ) {
266
						return;
267
					}
268
					// ignore change event if nothing changed
269
					if ( c && val !== $target.data( 'ts-original-value' ) || isCheckbox ) {
270
						$target.data( 'ts-original-value', val );
271
						c.table.tablesorterBusy = true;
272
						// pass undefined resort value so it falls back to config.resort setting
273
						$.tablesorter.updateCell( c, $cell, undef, function() {
274
							updateServer( event, c.$table, $target );
275
							c.table.tablesorterBusy = false;
276
						});
277
					}
278
				}
279
			});
280
 
281
			// add code for a checkbox in the header to set/unset all checkboxes in a column
282
			if ( $( this ).children( 'thead' ).find( 'input[type="checkbox"]' ) ) {
283
				$( this )
284
				.off( namespace )
285
				.on( 'tablesorter-ready' + namespace, function() {
286
					var checkboxClass,
287
						$table = $( this ),
288
						c = $table.length && $table[ 0 ].config;
289
					if ( !$.isEmptyObject( c ) ) {
290
						this.tablesorterBusy = true;
291
						checkboxClass = c && c.checkboxClass || 'checked';
292
						// set indeterminate state on header checkbox
293
						updateHeaderCheckbox( $table, checkboxClass );
294
						this.tablesorterBusy = false;
295
					}
296
				})
297
				.children( 'thead' )
298
				.add( this.config.widgetOptions.$sticky )
299
				.off( namespace )
300
				// modified from http://jsfiddle.net/abkNM/6163/
301
				// click needed for IE; a change isn't fired when going from an indeterminate checkbox to
302
				// either checked or unchecked
303
				.on( 'click' + namespace + ' change' + namespace, 'input[type="checkbox"]', function( event ) {
304
					var c, undef, onlyVisible, column, $target, isParsed, checkboxClass,
305
						$checkbox = $( this ),
306
						isChecked = this.checked,
307
						$table = $checkbox.closest( 'table' ),
308
						isSticky = $table.length && $table[0].className.match(/(tablesorter\w+)_extra_table/);
309
					if (isSticky) {
310
						isSticky = isSticky[1];
311
						$table = $('.' + isSticky + ':not(.' + isSticky + '_extra_table)');
312
					}
313
					c = $table.length && $table[ 0 ].config;
314
					if ( $table.length && c && !$table[ 0 ].tablesorterBusy ) {
315
						column = parseInt( $checkbox.closest( 'td, th' ).attr( 'data-column' ), 10 );
316
						isParsed = c.parsers[ column ].id === 'checkbox';
317
						onlyVisible = c.checkboxVisible;
318
						$table[ 0 ].tablesorterBusy = true; // prevent "change" event from calling updateCell numerous times (see #971)
319
						updateCheckbox(
320
							$target = $table
321
								.children( 'tbody' )
322
								.children( 'tr' + ( typeof onlyVisible === 'undefined' || onlyVisible === true ? ':visible' : '' ) )
323
								.children( ':nth-child(' + ( column + 1 ) + ')' ),
324
							isChecked
325
						);
326
						// add checkbox class names to row
327
						checkboxClass = c.checkboxClass || 'checked';
328
						$target.each( function() {
329
							toggleRowClass( $( this ).closest( 'tr' ), checkboxClass, column, isChecked );
330
						});
331
						if (isSticky) {
332
							// make main table checkbox match sticky header checkbox
333
							updateCheckbox($table.children( 'thead' ).find( '[data-column="' + column + '"]' ), isChecked);
334
						} else if (c.widgetOptions.$sticky) {
335
							updateCheckbox(c.widgetOptions.$sticky.find( 'thead' ).find( '[data-column="' + column + '"]' ), isChecked);
336
						}
337
						updateHeaderCheckbox( $table, checkboxClass );
338
						if ( isParsed ) {
339
							// only update cache if checkboxes are being sorted
340
							$.tablesorter.update( c, undef, function() {
341
								updateServer( event, $table, $target );
342
								$table[ 0 ].tablesorterBusy = false;
343
							});
344
						} else {
345
							updateServer( event, $table, $target );
346
							$table[ 0 ].tablesorterBusy = false;
347
						}
348
						// needed for IE8
349
						return true;
350
					}
351
					// update already going on, don't do anything!
352
					return false;
353
				});
354
			}
355
 
356
		});
357
	});
358
 
359
})( jQuery );