diff --git a/docs/example-widget-filter-search-trigger.html b/docs/example-widget-filter-search-trigger.html new file mode 100644 index 000000000..0de096350 --- /dev/null +++ b/docs/example-widget-filter-search-trigger.html @@ -0,0 +1,392 @@ + + + + + + jQuery tablesorter 2.0 - searchTrigger Filter Widget Functions + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

+
+

Demo

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First NameLast NameCityAgeTotalDiscountDate
AaronJohnson SrAtlanta35$5.9522%Jun 26, 2004 7:22 AM
AaronJohnsonYuma12$2.995%Aug 21, 2009 12:21 PM
ClarkHenry JrTampa51$42.2918%Oct 13, 2000 1:15 PM
DenniHenryNew York28$9.9920%Jul 6, 2006 8:14 AM
JohnHoodBoston33$19.9925%Dec 10, 2002 5:14 AM
ClarkKent SrLos Angeles18$15.8944%Jan 12, 2003 11:14 AM
PeterKent EsqSeattle45$153.1944%Jan 18, 2021 9:12 AM
PeterJohnsMilwaukee13$5.294%Jan 8, 2012 5:11 PM
AaronEvanChicago24$14.1914%Jan 14, 2004 11:23 AM
BruceEvansUpland22$13.1911%Jan 18, 2007 9:12 AM
ClarkMcMastersPheonix18$55.2015%Feb 12, 2010 7:23 PM
DennisMastersIndianapolis65$123.0032%Jan 20, 2001 1:12 PM
JohnHoodFort Worth25$22.0917%Jun 11, 2011 10:55 AM
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First NameLast NameCityAgeTotalDiscountDate
AaronJohnson SrAtlanta35$5.9522%Jun 26, 2004 7:22 AM
AaronJohnsonYuma12$2.995%Aug 21, 2009 12:21 PM
ClarkHenry JrTampa51$42.2918%Oct 13, 2000 1:15 PM
DenniHenryNew York28$9.9920%Jul 6, 2006 8:14 AM
JohnHoodBoston33$19.9925%Dec 10, 2002 5:14 AM
ClarkKent SrLos Angeles18$15.8944%Jan 12, 2003 11:14 AM
PeterKent EsqSeattle45$153.1944%Jan 18, 2021 9:12 AM
PeterJohnsMilwaukee13$5.294%Jan 8, 2012 5:11 PM
AaronEvanChicago24$14.1914%Jan 14, 2004 11:23 AM
BruceEvansUpland22$13.1911%Jan 18, 2007 9:12 AM
ClarkMcMastersPheonix18$55.2015%Feb 12, 2010 7:23 PM
DennisMastersIndianapolis65$123.0032%Jan 20, 2001 1:12 PM
JohnHoodFort Worth25$22.0917%Jun 11, 2011 10:55 AM
+
+ +

Javascript

+
+

+		
+ +

HTML

+
+

+		
+ +
+
+ Next up: Filter Widget ›› +
+
+ + + \ No newline at end of file diff --git a/docs/example-widget-filter.html b/docs/example-widget-filter.html index 48a1984f4..280fc1365 100644 --- a/docs/example-widget-filter.html +++ b/docs/example-widget-filter.html @@ -603,7 +603,11 @@

NOTE This table includes very basic infor true Allow searching through already filtered rows in special circumstances; will speed up searching in large tables if true. - + + filter_searchTrigger + false + If String,Number,Object, search is only triggered by the given types, see here + filter_selectSource null @@ -621,7 +625,7 @@

NOTE This table includes very basic infor false If true, filter will be done server-side. The client-side filtering will be disabled, but the ui and events will still be used. - + filter_startsWith false diff --git a/docs/index.html b/docs/index.html index c9e103ec7..c89af6090 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3511,7 +3511,44 @@

Comparison example

1 2 - + + + Boolean,String,Number,Object + false + + Filter widget: If set, only passed Keys/Events are used to trigger the search. + filter_liveSearch must be set to false +
+
+ Use the filter_searchTrigger option as follows: +
$(function() {
+  $("table").tablesorter({
+    widgets: ["filter"],
+    widgetOptions : {
+      filter_searchTrigger : [
+		  {
+			  keycode : $.tablesorter.keyCodes.enter, ctrl : true, alt : false, shift : false
+		  },
+		  $.tablesorter.keyCodes.tab,
+		  "blur"
+	  ]
+    }
+  });
+});
+ +
+ + Example + String diff --git a/js/widgets/widget-filter.js b/js/widgets/widget-filter.js index c6953acc9..5bf654e66 100644 --- a/js/widgets/widget-filter.js +++ b/js/widgets/widget-filter.js @@ -18,6 +18,7 @@ $.extend( tskeyCodes, { backSpace : 8, + tab : 9, escape : 27, space : 32, left : 37, @@ -55,11 +56,12 @@ filter_saveFilters : false, // Use the $.tablesorter.storage utility to save the most recent filters filter_searchDelay : 300, // typing delay in milliseconds before starting a search filter_searchFiltered: true, // allow searching through already filtered rows in special circumstances; will speed up searching in large tables if true + filter_searchTrigger : false, // array of events / Keys who trigger the search false = search, blur event and enterkey filter_selectSource : null, // include a function to return an array of values to be added to the column filter select filter_selectSourceSeparator : '|', // filter_selectSource array text left of the separator is added to the option value, right into the option text filter_serversideFiltering : false, // if true, must perform server-side filtering b/c client-side filtering is disabled, but the ui and events will still be used. filter_startsWith : false, // if true, filter start from the beginning of the cell contents - filter_useParsedData : false // filter all data using parsed content + filter_useParsedData : false // filter all data using parsed content }, format: function( table, c, wo ) { if ( !c.$table.hasClass( 'hasFilters' ) ) { @@ -458,6 +460,24 @@ c.$table.triggerHandler( 'filterFomatterUpdate' ); }, 100); } + // check if search is included because enter trigger a search event + if ( event.type === 'search' ) { + var triggerSearch = false, + searchTrigger = wo.filter_searchTrigger === false ? [ 'blur', tskeyCodes.enter ] : wo.filter_searchTrigger; + // skip search if not included + for ( var t in searchTrigger ) { + var stType = typeof searchTrigger[t], + trigger = searchTrigger[t]; + // only events required + if ( stType === 'string' && event.type === trigger ) { + triggerSearch = true; + break; + } + } + if ( !triggerSearch ) { + return; + } + } // pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first // input ensures all inputs are updated when a search is triggered on the table // $( 'table' ).trigger( 'search', [...] ); @@ -836,7 +856,8 @@ wo = table.config.widgetOptions; // make sure "wo" isn't cached var column = parseInt( $( this ).attr( 'data-column' ), 10 ), liveSearch = typeof wo.filter_liveSearch === 'boolean' ? wo.filter_liveSearch : - ts.getColumnData( table, wo.filter_liveSearch, column ); + ts.getColumnData( table, wo.filter_liveSearch, column ), + searchTrigger = wo.filter_searchTrigger; if ( typeof liveSearch === 'undefined' ) { liveSearch = wo.filter_liveSearch.fallback || false; } @@ -851,12 +872,43 @@ ( typeof liveSearch === 'number' && this.value.length < liveSearch ) || // let return & backspace continue on, but ignore arrows & non-valid characters ( event.which !== tskeyCodes.enter && event.which !== tskeyCodes.backSpace && - ( event.which < tskeyCodes.space || ( event.which >= tskeyCodes.left && event.which <= tskeyCodes.down ) ) ) ) ) { + ( event.which < tskeyCodes.space || ( event.which >= tskeyCodes.left && event.which <= tskeyCodes.down ) ) ) && + searchTrigger === false ) ) { return; // live search } else if ( liveSearch === false ) { - if ( this.value !== '' && event.which !== tskeyCodes.enter ) { - return; + if ( searchTrigger === false ) { + if ( this.value !== '' && event.which !== tskeyCodes.enter ) { + return; + } + } else { + var skipSearch = true; + // on keyup event only keycodes needed to be checked + for ( var t in searchTrigger ) { + var stType = typeof searchTrigger[t], + trigger = searchTrigger[t]; + // single keycode + if ( stType === 'number' && event.which === trigger ) { + skipSearch = false; + break; + } else if ( stType === 'object' ) { + // keyCode property must be in the object + if ( typeof trigger.keyCode === 'number' && event.which === trigger.keyCode || + tskeyCodes[ trigger.keyCode ] !== undefined && + event.which === tskeyCodes[ trigger.keyCode ] ) { + // check modifier + var ctrl = typeof trigger.ctrl === 'undefined' ? true : trigger.ctrl === event.ctrlKey, + alt = typeof trigger.alt === 'undefined' ? true : trigger.alt === event.altKey, + shift = typeof trigger.shift === 'undefined' ? true : trigger.shift === event.shiftKey; + if ( ctrl && alt && shift ) { + skipSearch = false; + } + } + } + } + if ( skipSearch ) { + return; + } } } // change event = no delay; last true flag tells getFilters to skip newest timed input @@ -869,25 +921,64 @@ eventType = event.type, liveSearch = typeof wo.filter_liveSearch === 'boolean' ? wo.filter_liveSearch : - ts.getColumnData( table, wo.filter_liveSearch, column ); - if ( table.config.widgetOptions.filter_initialized && - // immediate search if user presses enter - ( event.which === tskeyCodes.enter || - // immediate search if a "search" or "blur" is triggered on the input - ( eventType === 'search' || eventType === 'blur' ) || - // change & input events must be ignored if liveSearch !== true - ( eventType === 'change' || eventType === 'input' ) && - // prevent search if liveSearch is a number - ( liveSearch === true || liveSearch !== true && event.target.nodeName !== 'INPUT' ) && - // don't allow 'change' or 'input' event to process if the input value - // is the same - fixes #685 - this.value !== c.lastSearch[column] - ) - ) { - event.preventDefault(); - // init search with no delay - $( this ).attr( 'data-lastSearchTime', new Date().getTime() ); - tsf.searching( table, eventType !== 'keypress' || event.which === tskeyCodes.enter, true, column ); + ts.getColumnData( table, wo.filter_liveSearch, column ), + searchTrigger = wo.filter_searchTrigger === false ? ['blur' , 'search', tskeyCodes.enter ] : wo.filter_searchTrigger, + triggerSearch = false; + + if ( table.config.widgetOptions.filter_initialized ) { + // Only if liveSearch is disabled + if ( liveSearch === false ) { + // if ( eventType === 'search' ) { + // triggerSearch = true; + // } else { + for ( var t in searchTrigger ) { + var stType = typeof searchTrigger[t], + trigger = searchTrigger[t]; + // events + if ( stType === 'string' && eventType === trigger) { + triggerSearch = true; + break; + } else if ( stType === 'number' && event.which === trigger ) { + // keys + triggerSearch = true; + break; + } else if ( stType === 'object' ) { + // key combinations + if ( typeof trigger.keyCode === 'number' && event.which === trigger.keyCode || + tskeyCodes[ trigger.keyCode ] !== undefined && + event.which === tskeyCodes[ trigger.keyCode ] ) { + // same keycode + triggerSearch = true; + // check modifier + if ( typeof trigger.ctrl !== 'undefined' && trigger.ctrl !== event.ctrlKey ) { + triggerSearch = false; + } + if ( typeof trigger.alt !== 'undefined' && trigger.alt !== event.altKey ) { + triggerSearch = false; + } + if ( typeof trigger.shift !== 'undefined' && trigger.shift !== event.shiftKey ) { + triggerSearch = false; + } + } + } + } + //} + // change & input events must be ignored if liveSearch !== true + } else if ( ( eventType === 'change' || eventType === 'input' ) && + // prevent search if liveSearch is a number + ( liveSearch === true || liveSearch !== true && event.target.nodeName !== 'INPUT' ) && + // don't allow 'change' or 'input' event to process if the input value + // is the same - fixes #685 + this.value !== c.lastSearch[column]) { + triggerSearch = true; + } + + if ( triggerSearch ) { + event.preventDefault(); + // init search with no delay + $( this ).attr( 'data-lastSearchTime', new Date().getTime() ); + tsf.searching( table, eventType !== 'keypress' || event.which === tskeyCodes.enter, true, column ); + } } }); }, @@ -1955,4 +2046,4 @@ return valid.length !== 0; }; -})( jQuery ); +})( jQuery ); \ No newline at end of file