How to trigger a call when typing is stopped - javascript

<input autocomplete="off" [config]="config2" [items]="items2" (inputChangedEvent)="onInputChangedEvent($event)" (selectEvent)="onSelect($event)">`enter code here`
onInputChangedEvent(val: string) {
this.changeEvent.emit(val);
this.inputChanged = val;
if (this.timer) {
clearTimeout(this.timer);
}
// trigger the search action after 400 millis
this.timer = setTimeout(this.searchFunction(val), 200);
}
I am using InputChangedEvent ,how can we delay the event

You can't pass a function with arguments to setTimeout(), you need to create another function where in you call this function:
var _this = this;
setTimeout(function () {
_this.searchFunction(val);
}, 200);
By passing the function directly to setTimeout, JavaScript executes the function and uses the return value as the callback. So your searchFunction is executed every time.

Are you asking how to trigger the action only if there has been no typing for 400msec?
If so, the usual approach is a "deadman's switch" (name borrowed from an old safety device on trains, I believe).
The basic idea is that each time you see a keystroke, you kill the existing timer (if any) and start a timer for 400msec.
Then, if the timer finally triggers, you know that 400msec have passed without a keystroke, and you can do the action.

Related

Angular 6 setTimeout and clearTimeout error

I have an angular 6 strange problem.
I am using setTimeout and clearTimeout functions to start/cancel the timeout.
However this sometimes works, and sometimes doesn't.
Even if the user triggers an (click) event and the clearTimeout is run, sometimes it forces player to draw two cards.
Here is the code
//an event that says we must call uno
this._hubService.mustCallUno.subscribe(() => {
this.mustCallUno = true;
this._interval = window.setInterval(() => {
this.countdown -= 100;
}, 100);
this._timer = window.setTimeout(() => {
if (this.mustCallUno) {
this.drawCard(2);
this.callUno();
}
}, 2000);
});
// a function player calls from UI to call uno and not draw 2 cards
callUno() {
this.mustCallUno = false;
window.clearTimeout(this._timer);
window.clearInterval(this._interval);
this.countdown = 2000;
}
So even if the player calls callUno() function, the setTimeout is executed. Even worse, the code goes through the first if check inside the setTimeout if( this.mustCallUno) which by all means should be false since we just set it to false when we called callUno() function this.mustCallUno = false;.
I used setTimeout (returns NodeJS.Timer) before window.setTimeout and the result was the same.
You're using angular6+, so I suggest you to use reactive programming library such as rxjs
I made you a small example here.
Check for the possibility where function in this._hubService.mustCallUno.subscribe is run twice or multiple times, usually initially which you might not be expecting. Put a logger in function passed to mustCallUno.subscribe and callUno.
In this case what might be happening is this._timer and this._interval will have a different reference while the old references they hold, were not cleared because callUno is not called or is called less number of times than the callback in subscribe.

Efficient way to request back-end for data on input change

This is more of a suggestion asking kind of question! I have a searchbox that user can type stuff in and the get a list of suggestion to choose from. I am using react, axios for data fetching and redux-saga for state managing.It is basically look like this:
handleChange(stringValue){
this.setState({
inputValue : stringValue
});
callServer(stringValue);
}
Now, everything works fine but the problem is that sending all those requests and handling the incoming response and changing state seems unnecessary because user doesn't stop to look at the suggestions in every char he types. I am looking for a way to only ask for suggestions when i know user is done fast typing. What i am thinking of doing looks like this :
handleChange(stringValue){
clearTimeOut(this.callerTimer);
this.callerTimer = null;
this.callerTimer = setTimeOut(function(){
this.callServer(stringValue);
this.callerTimer = null;
}.bind(this),300)
//i consider 300ms as the average time it takes people to stop typing and think
}
This works but i don't have a good feeling about it. So do you guys know any other clean and less timerly way to do what i want? is there any way to handle this in my saga effect or maybe an inbuilt time threshold thing in inputs that i am not aware of?
You want debounce functionality.
Basically it limits the rate at which a function can fire. So it waits a few ms before firing the event kind of like the user stopping the writing process.
Check this snippet
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
// This will apply the debounce effect on the keyup event
// And it only fires 500ms or half a second after the user stopped typing
$('#testInput').on('keyup', debounce(function () {
alert('typing occurred');
$('.content').text($(this).val());
}, 500));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="testInput" />
<p class="content"></p>
Check this codesandbox for React solution
https://codesandbox.io/embed/green-meadow-16r3p?fontsize=14
Basically now it's up to you. Set your own time in ms and you're good to go. There is no need to install any additional dependencies to your project.
Lodash has a debounce function but you don't want to install all of lodash just for one function.
I highly recommend using debounce from lodash: https://lodash.com/docs/4.17.11#debounce
From the docs:
Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked.
Therefore you pass your request function to debounce, so you limit the number of requests to your server.

jquery pause before displaying next step

On button next click (Game context), I want to make pause to show correct answer before showing next question. how can I do it?
I try this :
showCorrectAnswer();
questionCounter++;
setTimeout(displayNext(), 6000);
/* Or */
showCorrectAnswer();
questionCounter++;
wait(6000);
displayNext();
/*with wait*/
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
But does not work.
Thanks
You are supposed to pass either an anonymous function to setTimeout() (in which you place what you want to execute when the timeout expires) or the name of a defined function. If you place () after the name, as you did, the function is executed when the setTimeout() is parsed, not when it expires, expecting the result of running your function to return another function that will be executed when the setTimeout() expires - much like the anonymous function does.
Either of the following will work as expected. Name of function:
showCorrectAnswer();
questionCounter++;
setTimeout(displayNext, 6000);
...or anonymous wrapper:
showCorrectAnswer();
questionCounter++;
setTimeout(function(){
displayNext();
}, 6000);
In most real life scenarios, it is advisable to change questionCounter value inside the displaynNext() function, not before.
With jquery you can use:
$('.container').hide().delay(6000).fadeIn(displayNext());
check out this
you have done a small mistake setTimeout(displayNext(),6000) which calls immediately instead you should only pass function name. setTimeout(displayNext,6000)
If you want to do call with parameters make sure you write as a function and then put all your code inside it setTimeout(function(){displayNext(parameter1,parameter2);},6000)
function displayNext(){
alert("display");
}
<input type="number" step="1000" id="num_milisecond" value=1000> milliseconds
<input type="button" onclick="setTimeout(displayNext, document.getElementById('num_milisecond').value);" value="click to allert">

Javascript - call a function when you finish typing

Let's say I have an input in wich the user is going to type some text. When he finish typing I want to call a function automatically.
This is what I have done till now:
<input type="text" oninput="change();"/>
<script>
function changing(){
alert('You stoped typing!');
}
function change(){
clearTimeout(changing);
setTimeout(changing, 2000);
}
</script>
What I am expecting :
When you type, change is called. It cancels the last changing that was supposed to run in 2 seconds and run a new changing within 2 seconds.
What actually happens :
When you type, change is called. It doesn't cancel the last changing that was supposed to run in 2 seconds but still run a new changing within 2 seconds. As you type, the first alert window will appear 2 seccond after you start typing and keep showing again and again one after another.
Is there something wrong in my code?
setTimeout() returns a timer ID. It is that timer ID that you must pass to clearTimeout() for it to work properly (you are passing the callback function to clearTimeout() and that is not how it works).
So, you need to store the return value from setTimeout() into a variable in a lasting scope that you can then later pass to clearTimeout() like this:
<input type="text" oninput="change();"/>
<script>
function changing(){
alert('You stoped typing!');
}
var timer;
function change(){
clearTimeout(timer);
timer = setTimeout(changing, 2000);
}
</script>
The setTimeout() function returns a value that must be used later with clearTimeout() if you need to cancel it.
var timer;
function changing(){
alert('You stoped typing!');
}
function change(){
clearTimeout(timer);
timer = setTimeout(changing, 2000);
}

Javascript time counter for calling ajax

I have a number of different form elements. When any of the form elements have their value changed, I need to make an ajax call 500ms after the change.
However, should another form element have its value changed then I would like to reset the timer to 500ms, thus avoiding multiple Ajax requests for a series of changes that happen within 500ms of each other.
Is there a JavaScript or jQuery solution to this requirement?
Here's some code that demonstrates the principles you're looking for:
// Keeps track of the timer id in a scope that is outside of the event function
// The variable will remain in memory and available to the next event call
var myTimer;
// Detect changes on keyup.
$('.textbox').on('keyup', function () {
console.log('keyup');
setMyTimer(500);
});
// Detect on change.
$('select').on('change', function () {
console.log('change');
setMyTimer(1000);
});
function setMyTimer(timerDelay) {
// if myTimer has a value, then we should clear the timer. This stops us
// from queuing multiple timers
if (myTimer) {
console.log('clear tiemout');
clearTimeout(myTimer);
}
// Set the timer. It will be cleared if there is another handled 'keyup'
// event sooner than the timerDelay parameter
myTimer = setTimeout(function () {
console.log('Ajax stuff');
// ajax stuff
}, timerDelay);
};
Remove the console.log code before using in production.
See this working demonstration:
http://jsfiddle.net/cC6Dq/5/

Categories

Resources