How to clear all running timeouts before setting a new timeout - javascript

When I click the mic icon two times simultaneously it comes back to inactive state but the timeout function still takes place.
Below are my console values :
true
false
false
Instead of:
true
false
How to prevent this from happening.
// Start listening on click.
var active= false;
var $mic = $("#mic-container");
$mic.click(function(event){
//event.preventDefault();
// if we're recording when the button is clicked
if(active) {
$mic.removeClass("active pulse");
active=false; console.log(active);
annyang.abort();
// if we're not recording when the button is clicked
} else {
annyang.start({ autoRestart: false, continuous: false }); // start listening
active = true; console.log(active); // set recording var to true
$mic.addClass('active pulse'); // turn on active class
setTimeout(function(){
$mic.removeClass("active pulse");
active=false; console.log(active);
annyang.abort();
}, 8000);
}
});
annyang.addCallback('resultNoMatch', function () {
$('.myErrorText').html('Try saying a valid command. See help section for a list of valid commands!');
$mic.addClass("result-no-match");
setTimeout(function(){
$mic.removeClass("active pulse result-no-match");
active=false; console.log(active);
annyang.abort();
}, 500);
});
annyang.addCallback('resultMatch', function () {
$('.myErrorText').text('');
$mic.addClass("result-match");
setTimeout(function(){
$mic.removeClass("active pulse result-match");
active=false; console.log(active);
annyang.abort();
}, 500);
});

Even i had the same kind of problem. Try this
// Start listening on click.
var timeoutHandle;
var active= false;
var $mic = $("#mic-container");
$mic.click(function(event){
//event.preventDefault();
if(active)
annyang.abort();
else
annyang.start({ autoRestart: false, continuous: false});
});
annyang.addCallback('start', function () {
active = true; console.log(active);
$mic.addClass('active pulse');
window.clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(annyang.abort, 5000);
});
annyang.addCallback('end', function () {
window.clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function () {$mic.removeClass("active pulse result-match result-no-match");}, 200);
active=false; console.log(active);
});
annyang.addCallback('resultNoMatch', function () {
$mic.addClass("result-no-match");
$('.myErrorText').html('Try saying a valid command. See help section for a list of valid commands!');
});
annyang.addCallback('resultMatch', function () {
$('.myErrorText').text('');
$mic.addClass("result-match");
});

Assign the timeout to a variable and then just call the clearTimeout() method when you want to kill the timer. For example:
var resultMatchTimer = null;
// stops the timer
if(resultMatchTimer) {
clearTimeout(resultMatchTimer);
resultMatchTimer = null;
}
// starts the timer
resultMatchTimer = setTimeout(..., ...);

You should store the result (handle) of setTimeout in a var and call clearTimeout on that handle.
var timeoutHandle = setTimeout(...);
clearTimeout(timeoutHandle); // this will clear the timeout.
With the correct scoping, you can call clearTimeout from all your clicks, and decide you need 3 handles to clear them individually or just use one form all setTimeouts and just clear it. When een new setTimeout is called your handle will be overwritten so make sure your clear the other timeout before that.

The problem is that timeouts are being started while those from previous clicks are still counting.
You're going to have to keep track of the active timeouts, and cancel them if they're running while the user clicks again.
This is possible because setTimeout returns an identifier you can pass to clearTimeout to, as the function name suggests, cancel the timeout.
For example:
var resultMatchTimeout; // Variable to store a reference to a timeout in.
annyang.addCallback('resultMatch', function () {
$('.myErrorText').text('');
$mic.addClass("result-match");
if(resultMatchTimeout){ // If a timeout is running, cancel it.
clearTimeout(resultMatchTimeout);
resultMatchTimeout = null;
}
resultMatchTimeout = setTimeout(function(){ // Save a reference to the current timeout.
$mic.removeClass("active pulse result-match");
active=false; console.log(active);
annyang.abort();
}, 500);
});
You're going to have to do this for your other setTimeout calls too, obviously.
Just make sure to use different variables for each of the timeouts, otherwise, you 'll be cancelling the wrong timout.

One more thing to consider: set the active/not-active state based on the actual voice recognition engine state and not based on user clicks.
Check annyang.isListening()

Every setTimeout() returns a unique Id which could be used to clear the timeout using clearTimeout.
I can see that you have multiple timers running, so what you could do is store all the ids returned each time from setTimeout method in a array and use the same array to clear all the timers in a loop.
MDN reference: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
JS CODE:
var myVar;
function myFunction() {
myVar = setTimeout(function(){ alert("Hello"); }, 3000);
}
function myStopFunction() {
clearTimeout(myVar);
}
Note: This is just a generic solution, which can be a base for final/actual solution

Related

clearInterval() does not seem to work as expected

I am developing a JavaScript/WebRTC walkie-talkie app and require a button to be held down to send audio. It works fine until I click the right mouse button whilst holding the left which causes the setInterval function to continue working and clearInterval unable to stop it via its ID. It just continues on forever. According to everything I have read, clearInterval should stop it, especially if the interval is set globally.
var intervalId;
$("#transmitbutton").on("mousedown touchstart", function () {
intervalId = setInterval(function () {
console.log("PTT pressed");
}, 1000);
});
$("#transmitcontainer").on("mouseup touchend mouseleave", function () {
clearInterval(intervalId);
});
I have tried the start and stop buttons and it has the same outcome. clearInterval is not working.
var intervalId;
$("#transmitstart").on("click", function () {
intervalId = setInterval(function () {
console.log("PTT pressed");
}, 1000);
});
$("#transmitstop").on("click", function () {
clearInterval(intervalId);
});
If you happen to call your function that creates it more then one time you will have an interval that will not be cancelable since you will overwrite the interval id. So either you need to cancel it, or not make a new interval.
var intervalId;
$("#transmitbutton").on('mousedown touchstart', function() {
if (intervalId) return; // either exit out and not create a new one
// if (intervalId) clearInterval(intervalId); //or remove it here
intervalId = setInterval(function(){
console.log("PTT pressed");
}, 1000);
});
$("#transmitcontainer").on('mouseup touchend mouseleave', function() {
if (intervalId) clearInterval(intervalId);
intervalId = null;
});

How to check which timer is running in jquery.each loop

I am using easytimer (https://github.com/albert-gonzalez/easytimer.js) and I got into an issue.
I create multiple timer on one page, each timer has its own start and stop button.
Now I want to make sure there is only one timer running at the same time.
So I imagine if I click start button of timer 3, it should check all other timers if they are running then stop them.
Below is my code
$('tr.step').each(function (index) {
var timer = new easytimer.Timer();
btnStart.off('click').on('click', (event) => {
event.preventDefault();
if (timer.isRunning()) {
console.log(timer + index + 'is running');
}
timer.start({
callback: function (timer) {
valTimer.html(
timer.getTimeValues().toString()
);
}
});
btnStart.hide();
btnStop.fadeIn(1000);
});
btnStop.off('click').on('click', (event) => {
event.preventDefault();
timer.stop();
});
So anyone please help me how to check which timer is running and stop it before start counting a new one.

How to fire an event after n seconds of maintained click? - jQuery/Javascript

I am sure I am not the first looking for this, but I did not find any solution to my problem..
I am looking for a way to fire an event after and only after a 3 seconds maintained click.
I tried with javascript setInterval() function with mouseup/mousedown Jquery events but it did't work.
Someone has an idea ?
I have a div, I keep the mouse button down for 3 seconds, and something will be fired.
3 seconds timer must be reinitialized every time.
Call setTimeout() to perform your action after 3000 milliseconds, storing the identifier from setTimeout() into a variable scoped above the function. On the element's mouseup(), clear the timeout if it exists via clearTimeout().
var divMouseDown;
$('#div-id').mousedown(function() {
divMouseDown = setTimeout(function() {
// Do timeout action...
}, 3000);
});
$('#div-id').mouseup(function() {
if (divMouseDown) {
clearTimeout(divMouseDown);
}
});
On mouse down, set a timeout for 3 seconds in the future.
On mouse up, clear the timeout.
$('#div').on('mousedown', function(){
mousetimer.down();
}).on('mouseup', function(){
mousetimer.cancel();
});
var mousetimer = {
timer: null,
timing: false,
down: function(){
if(!timing)
{
mousetimer.timing = true;
mousetimer.timer = setTimeout(function(){
mousetimer.trigger();
}, 3000);
}
},
trigger: function(){
alert('do something');
mousetimer.cancel();
},
cancel: function(){
mousetimer.timing = false;
clearTimeout(mousetimer.timer);
}
};
Seems like mouseup/mousedown events and setTimeout/clearTimeout is the way to do it:
var timer = null;
$(selector).on('mousedown', function(ev) {
timer = setTimeout(function() {
timer = null;
/* Do something */
}, 3000);
}.on('mouseup', function(ev) {
if (timer) {
clearTimeout(timer);
timer = null;
}
});
Use a timeout of 3000ms.
Set the timeout on the mouse down event, clear it on the mouse up event.
http://jsfiddle.net/kHMWX/

javascript/jquery - add debounce to a button

I want to add a debounce to a button, but i want to perform some actions each time user clicks button, but only after 5 second after user hits button, then perform SQL update. Usually the throttle seems to be applied directly to the listener. Here I want some actions performed each time the button is clicked, and then an update after a reasonable waiting period.
I am not sure how to use the function in this case...
reference: http://code.google.com/p/jquery-debounce/
$('#myButton').click(function() {
// do a date calculation
// show user changes to screen
// wait until user has has stopped clicking the
// button for 5 seconds, then update file with "process" function.
});
function process(){
// update database table
}
debounce syntax
$('input').bind('keyup blur', $.debounce(process, 5000));
You could still use $.debounce like so:
// create new scope
(function() {
// create debounced function
var dprocess = $.debounce(process, 5000);
// bind event handler
$('#myButton').click(function() {
// do a date calculation
// show user changes to screen
// call the function
dprocess();
});
}());
Alternative without $.debounce (you can always debounce your code this way, without jQuery):
// create new scope
(function() {
var timer;
// bind event handler
$('#myButton').click(function() {
if(timer) {
clearTimeout(timer);
}
// do a date calculation
// show user changes to screen
// call the function
timer = setTimeout(process, 5000);
});
}());
Debounce using native/vanilla JS and jquery/underscore.js.
Example
JS
//Native/Vanilla JS
document.getElementById('dvClickMe').onclick = debounce(function(){
alert('clicked - native debounce');
}, 250);
function debounce(fun, mil){
var timer;
return function(){
clearTimeout(timer);
timer = setTimeout(function(){
fun();
}, mil);
};
}
//jQuery/Underscore.js
$('#dvClickMe2').click(_.debounce(function(){
alert('clicked - framework debounce');
}, 250));
HTML
<div id='dvClickMe'>Click me fast! Native</div>
<div id='dvClickMe2'>Click me fast! jQuery + Underscore</div>
var timer;
$('#myButton').click(function() {
//Called every time #myButton is clicked
if(timer) clearTimeout(timer);
timer = setTimeout(process, 5000);
});
function process(){
//Called 5000ms after #myButton was last clicked
}
Using a global variable might not be the best solution if the debounce function is used to debounce multiple functions. For that we should scope the timer to the function being denounced.
function debounce(func, timeout = 2000) {
if (func.timer) clearTimeout(func.timer);
func.timer = setTimeout(func, timeout);
}
debounce(func1, 4000);
debounce(func2, 1000);
NOTE: this won't work with an anonymous function;
Why not just use setTimeOut(function() { process(); }, 5000);

Detecting when the mouse is not moving

I am able to find the cursor position. But I need to find out if the mouse is stable. If the mouse wasn't moved for more than 1 minute, then we have to alert the user.
How its possible, are there any special events for this? (Only for IE in javascript)
Set a timeout when the mouse is moved one minute into the future, and if the mouse is moved, clear the timeout:
var timeout;
document.onmousemove = function(){
clearTimeout(timeout);
timeout = setTimeout(function(){alert("move your mouse");}, 60000);
}
Here's a one-and-done function that can check any element for movement:
function mouse (element, delay, callback) {
// Counter Object
element.ms = {};
// Counter Value
element.ms.x = 0;
// Counter Function
element.ms.y = function () {
// Callback Trigger
if ((++element.ms.x) == delay) element.ms.callback(element, element.ms);
};
// Counter Callback
element.ms.callback = callback;
// Function Toggle
element.ms.toggle = function (state) {
// Stop Loop
if ([0, "off"][state]) clearInterval(element.ms.z);
// Create Loop
if ([1, "on"][state]) element.ms.z = setInterval(element.ms.y, 1);
};
// Function Disable
element.ms.remove = function () {
// Delete Counter Object
element.ms = null; return delete element.ms;
};
// Function Trigger
element.onmousemove = function () {
// Reset Counter Value
element.ms.x = -1;
};
// Return
return element.ms;
};
Usage:
mouse(element, delay, callback)
Examples:
Make a video player hide the mouse after 5 seconds when idle and fullscreen
let x = mouse(video, 5000, function (a) {
if (document.webkitIsFullScreen) video.style.cursor = "none";
});
x.toggle(1); addEventListener("mousemove", function () {
video.style.cursor = "auto";
});
Chat Room AFK (45 Seconds) (assuming you have a chat box and a send message function):
let x = mouse(chatBox, (45e3), function (a) {
chatBox.send({ text: chatBox.username + " is AFK.", italic: true });
});
x.toggle(1); x.addEventListener("mousemove", function () {
chatBox.send({ text: chatBox.username + " is no longer AFK", italic: true });
});
Is there not a way to set a timer to start incrementing after every mouse movement event?
If it gets to a minute then pop up the message box, but every time the mouse moves the timer gets reset.
Use a timer that resets its value on mousemove event.
If timer reaches 1 minute --> Do something.
More info on timer here http://www.w3schools.com/js/js_timing.asp
And more info on catchin mouse events here http://www.quirksmode.org/js/events_mouse.html
Yes, you have a onmousemove event in Javascript, so to achieve what you need you just have to do code something like this:
startTimer();
element.onmousemove = stopTimer(); //this stops and resets the timer
You can use it on the document body tag for instance.
UPDATE: #Marius has achieved a better example than this one.
You can use the onmousemove event. Inside it, clearTimeout(), and setTimeout(your_warning, 1 minute).
You could use this script/snippet to detect the mouse pointer position and "remember" it. Then use a timer "setTimeout(...)" to check the position let's say every second and remember that time.
If more than one minute passed and the position hasn't changed, you could alert the user.

Categories