From f5218a761502aed36d37ba09710acfaa4f63bacd Mon Sep 17 00:00:00 2001 From: Josh Schmidt Date: Thu, 26 Oct 2023 14:30:17 -0600 Subject: [PATCH] debounce onInput. fixes #560 --- src/defaults.ts | 2 ++ src/tom-select.ts | 38 ++++++++++++++++++++++++++++---------- src/types/settings.ts | 1 + src/utils.ts | 12 ++++++++++++ test/support/base.js | 2 ++ 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/defaults.ts b/src/defaults.ts index c7537957..eef9aa8f 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -23,6 +23,8 @@ export default { preload: null, allowEmptyOption: false, //closeAfterSelect: false, + refreshThrottle: 300, + loadThrottle: 300, loadingClass: 'loading', diff --git a/src/tom-select.ts b/src/tom-select.ts index d9caf2f3..d33c070a 100644 --- a/src/tom-select.ts +++ b/src/tom-select.ts @@ -16,6 +16,7 @@ import { preventDefault, addEvent, loadDebounce, + timeout, isKeyDown, getId, addSlashes, @@ -87,6 +88,7 @@ export default class TomSelect extends MicroPlugin(MicroEvent){ public userOptions : {[key:string]:boolean} = {}; public items : string[] = []; + private refreshTimeout : null|ReturnType = null; constructor( input_arg: string|TomInput, user_settings:RecursivePartial ){ @@ -760,23 +762,39 @@ export default class TomSelect extends MicroPlugin(MicroEvent){ * */ onInput(e:MouseEvent|KeyboardEvent):void { - var self = this; + + if( this.isLocked ){ + return; + } - if( self.isLocked ){ + const value = this.inputValue(); + if( this.lastValue === value ) return; + this.lastValue = value; + + if( value == '' ){ + this._onInput(); return; } - var value = self.inputValue(); - if (self.lastValue !== value) { - self.lastValue = value; + if( this.refreshTimeout ){ + clearTimeout(this.refreshTimeout); + } + + this.refreshTimeout = timeout(()=> { + this.refreshTimeout = null; + this._onInput(); + }, this.settings.refreshThrottle); + } - if( self.settings.shouldLoad.call(self,value) ){ - self.load(value); - } + _onInput():void { + const value = this.lastValue; - self.refreshOptions(); - self.trigger('type', value); + if( this.settings.shouldLoad.call(this,value) ){ + this.load(value); } + + this.refreshOptions(); + this.trigger('type', value); } /** diff --git a/src/types/settings.ts b/src/types/settings.ts index df215694..8fe6c65f 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -31,6 +31,7 @@ export type TomSettings = { preload : boolean|string, allowEmptyOption : boolean, closeAfterSelect : boolean, + refreshThrottle : number, loadThrottle : number, loadingClass : string, diff --git a/src/utils.ts b/src/utils.ts index 33650cbb..4c61cad9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -40,6 +40,18 @@ export const escape_html = (str:string):string => { }; +/** + * use setTimeout if timeout > 0 + */ +export const timeout = (fn:()=>void,timeout:number) => { + if( timeout > 0 ){ + return setTimeout(fn,timeout); + } + + fn.call(null); + return null; +} + /** * Debounce the user provided load function * diff --git a/test/support/base.js b/test/support/base.js index 23821102..265e54be 100644 --- a/test/support/base.js +++ b/test/support/base.js @@ -65,6 +65,8 @@ window.setup_test = function(html, options, callback) { } if( select.nodeName == 'SELECT' || select.nodeName == 'INPUT' ){ + options = options || {}; + options.refreshThrottle = 0; instance = tomSelect(select,options); }