I am trying to show a message when a user is typing and hide the message after a timeout period is reached, I am using this logic with React Native and Gifted Chat.
updateTyping() {
var TYPING_TIMER_LENGTH= 1000;
if (this.state.connected) {
if (!this.state.typing) {
this.setState({typing : true})
console.log('typing')
}
var lastTypingTime = (new Date()).getTime();
setTimeout( () => {
var typingTimer = (new Date()).getTime();
var timeDiff = typingTimer - lastTypingTime;
if (timeDiff >= TYPING_TIMER_LENGTH && this.state.typing) {
console.log('Stop typing')
this.setState({typing : false});
}
}, TYPING_TIMER_LENGTH);
}
else{
console.log("Socket Cannot connect.")
}
}
Now the typing message keeps hiding and showing (blinking) even when the user is typing.
Logics
Now logically the typing message should show and if after 1000ms idle, the typing message hides.
Is there something I am not doing right from my snippet. Any Ideas would be much appreciated
Here's my implementation of doing your code but better (as explained in comment).
if (!this.state.typing) {
this.setState({typing : true})
console.log('typing')
} else {
clearTimeout(timeoutVar);
}
//var lastTypingTime = (new Date()).getTime();
timeoutVar = setTimeout( () => {
//you dont need to do this. either do this and no timeout,
//or do timeout and not this. It's virtually doing the same thing.
//
//var typingTimer = (new Date()).getTime();
//var timeDiff = typingTimer - lastTypingTime;
//if (timeDiff >= TYPING_TIMER_LENGTH && this.state.typing) {
console.log('Stop typing')
this.setState({typing : false});
//}
}, TYPING_TIMER_LENGTH);
The only important thing about this is you need to make sure that timeoutVar is defined somewhere outside of updateTyping, but accessible. Otherwise this doesn't work. The idea behind it is this: we set a timeout to do something and it's going to fire in the time we tell it to TYPING_TIMER_LENGTH, however every time we type something (assuming from your code this function gets hit when they type) we clear the timeout so it doesn't fire. The only time it fires is if we don't clear it, which will be if they stop typing (again, assuming from your code).
Hi I'm not good at react but upto my knowledge. Using timer is really a bad idea until or unless you the property is exact time bounded.
Sol:
Try to display the message using OnFocus and hide it when it goes away from that text box.
Related
Sorry this is going to take a bit of explaining so you know what I'm trying to do here...
I'm having trouble with a timer function. Basically when the user hits the page, an Ajax request is made, the result of which starts a timer function. They have a certain amount of time in which to make a payment (this is a block chain based payment app, payment is made via an external wallet - no user input is required on the payment page at all, no buttons to click etc). If the timer runs out the payment box resets.
But if the persistent Ajax calls running in the background find the users payment on the block chain I need to kill the timer as it is no longer required, but I need to keep the payment box open while the confirmations are being monitored until the transaction is complete.
The trouble is I can't alter the already running timer function. I've tried every way possible I could think of but nothing stops the original function from running and ultimately resetting the payment box while the transaction is ongoing (waiting for confirmations).
I have been reading about wrapping the timer function in an object and adding a listener but everything I found seemed really confusing to me.
Below is the relevant code.
The function that starts the timer is being started by the Ajax response from another function...
myTimer(expiry);
The expiry variable being passed is vital as it sets an intial on / off state for the timer (whether to display it or not from the first response). So I need to keep that.
This is the timer function...
function myTimer(expiry) {
// If expiry set to 0 don't use the timer
if (expiry === 0) {
$('#timer').hide();
return;
}
var start = new Date();
var timeoutVal = Math.floor(expiry/100);
animateUpdate();
function updateProgress(percentage) {
$('#timerInner').css("width", percentage + "%");
}
function animateUpdate() {
var now = new Date();
var timeDiff = now.getTime() - start.getTime();
var perc = Math.round((timeDiff/expiry)*100);
if (perc <= 100) {
updateProgress(perc);
setTimeout(animateUpdate, timeoutVal);
} else {
// Timer expired, clear box and show buy button again
$("#paymentWrap").empty();
$("#btn-Pay").show();
$("#btn-Pay").prop("disabled", false);
return;
}
}
}
}
This is the part that I need to "kill" on demand via another function coming from another Ajax response...
// Timer expired, clear box and show buy button again
$("#paymentWrap").empty();
$("#btn-Pay").show();
$("#btn-Pay").prop("disabled", false);
return;
Can somebody explain how I can add a variable listener to this function (maybe by creating it as an object?) so that I can change the chunk of code that triggers the bit above to include a new var called cancelled that can be updated elsewhere in the script WHILE this function is running.
if (perc <= 100) {
updateProgress(perc);
setTimeout(animateUpdate, timeoutVal);
if (cancelled === true) {
// Hide the timer div and kill the timer function
$("#timer").hide();
return;
}
} else {
// Timer expired, clear box and show buy button again
.......
I know this was really long winded, apologies upfront, but thanks for reading and looking forward to any help you can offer.
Cheers!
You can define a global variable to reference setTimeout() call and use cleaTimeout()
let timer = null;
let then_ = new Date().getTime() + 10000;
function fn() {
timer = setTimeout(function() {
console.log("doing stuff at " + new Date()
, "time remaining to do stuff:", then_ - new Date().getTime());
if (new Date().getTime() < then_) {
fn()
} else {
done()
}
}, 1000)
}
function done() {
clearTimeout(timer);
timer = null;
console.log("done doing stuff at " + new Date());
}
document.querySelector("button")
.onclick = function() {
if (timer) {
done()
} else {
this.onclick = null;
}
}
fn();
<button>clear timer</button>
I have an unusual problem. I'm using the following script to check for internet connection using navigator.onLine. If there is internet connection, the page will be refreshed every 15 seconds. If there isn't any internet connection, the page will use innerHTML to display a message.
<script type="text/javascript">
setInterval(function () {
if (navigator.onLine) {
var myInterval = setInterval(function(){window.location.href = "Tracker.html";},15000);
} else {
clearInterval(myInterval);
var changeMe = document.getElementById("change");
change.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
}
}, 250);
</script>
My problem is, once there is no internet connection, the message will be displayed, BUT the page would still be refreshed one last time. I'm trying to avoid this, by using clearInterval(myInterval); in the else part of the code, however it won't work.
Any suggestions?
To refresh the page at 15 second intervals (provided that a connection is present), use:
function refresh() {
if(navigator.onLine)
window.location.href = "Tracker.html";
else{
var changeMe = document.getElementById("change");
change.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
setTimeout(refresh, 250);
}
}
setTimeout(refresh, 15000);
At the end of 15 seconds, this checks whether a connection is present. If there is, it refreshes the page. If there isn't, it proceeds to check every 250 milliseconds afterwards until the user is reconnected, at which point it refreshes the page.
The net result is that the script refreshes the page as soon as possible after a minimum of 15 seconds have elapsed.
Here is a demonstration: http://jsfiddle.net/JGEt9/show
Whenever the outer interval callback is executed, a new myInterval variable is created and the previous one is lost (it goes out of scope because the callback terminates).
You have to persist the value of the variable between function calls by declaring it outside of the function. You also have to make sure that you are not creating another timeout if one is already running.
var timeout = null;
setInterval(function () {
if (navigator.onLine) {
if (timeout === null) {
timeout = setInterval(function(){window.location.href = "Tracker.html";},15000);
}
} else {
clearTimeout(timeout);
timeout = null;
// ...
}
}, 250);
You need to declare myInterval outside of the if statement. You should only need the refresh code once too. Something like this:
var myInterval = setTimeout(function(){window.location.href = "Tracker.html";},15000);
setInterval(function () {
if (!navigator.onLine) {
clearTimeout(myInterval);
var changeMe = document.getElementById("change");
changeMe.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
}
}, 250);
Here you set the refresh interval and continually check to see if the browser is offline, and if it is, you remove the timer and do your cleanup code. I also changed the refresh code to use setTimeout instead of interval because it only happens once.
Another issue is you create changeMe but then try to use change. change doesn't exist. I fixed that in my example as well.
Note: This will not resume refreshing once connection is regained. See Felix Kling's answer.
Is there a way to stop setTimeout("myfunction()",10000); from counting up when the page isn't active. For instance,
A user arrives at a "some page" and stays there for 2000ms
User goes to another tab, leaves "some page" open.
myfunction() doesn't fire until they've come back for another 8000ms.
(function() {
var time = 10000,
delta = 100,
tid;
tid = setInterval(function() {
if ( document.hidden ) { return; }
time -= delta;
if ( time <= 0 ) {
clearInterval(tid);
myFunction(); // time passed - do your work
}
}, delta);
})();
Live demo: https://jsbin.com/xaxodaw/quiet
Changelog:
June 9, 2019: I’ve switched to using document.hidden to detect when the page is not visible.
Great answer by Šime Vidas, it helped me with my own coding. For completeness sake I made an example for if you want to use setTimeout instead of setInterval:
(function() {
function myFunction() {
if(window.blurred) {
setTimeout(myFunction, 100);
return;
}
// What you normally want to happen
setTimeout(myFunction, 10000);
};
setTimeout(myFunction, 10000);
window.onblur = function() {window.blurred = true;};
window.onfocus = function() {window.blurred = false;};
})();
You'll see that the window blurred check has a shorter time set than normal, so you can set this depending on how soon you require the rest of the function to be run when the window regains focus.
You can do something like:
$([window, document]).blur(function() {
// Clear timeout here
}).focus(function() {
// start timeout back up here
});
Window is for IE, document is for the rest of the browser world.
I use almost the same approach as Šime Vidas in my slider
but my code is based on document.visibilityState for page visibility checking:
document.addEventListener("visibilitychange", () => {
if ( document.visibilityState === "visible" ) {
slideshow.play();
} else {
slideshow.pause();
}
});
About Page Visibility
API: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
What you'd have to do is set up a mechanism to set timeouts at small intervals, keeping track of total elapsed time. You'd also track "mouseenter" and "mouseleave" on the whole page (the <body> or something). When the short-term timeouts expire, they can check the window state (in or out) and not restart the process when the window is not in focus. The "mouseenter" handler would start all paused timers.
edit — #Šime Vidas has posted an excellent example.
I've finally implemented a variation of #Šime Vidas' answer, because the interval was still running if I opened another program and the browser window was not visible, but the page executing the interval was the active browser tab. So, I've modified the condition to document.hidden || !document.hasFocus(). This way, if the document is hidden or the document doesn't have the focus, the interval function just returns.
(function() {
var time = 10000,
delta = 100,
tid;
tid = setInterval(function() {
if ( document.hidden || !document.hasFocus() ) { return; }
time -= delta;
if ( time <= 0 ) {
clearInterval(tid);
myFunction(); // time passed - do your work
}
}, delta);
})();
Ok, firstly, I hardly know Javascript. I really don't know what I'm doing.
So, I have this code:
var interval_id = 0;
var prevent_bust = 0;
// Event handler to catch execution of the busting script.
window.onbeforeunload = function() { prevent_bust++ };
// Continuously monitor whether busting script has fired.
interval_id = setInterval(function() {
if (prevent_bust > 0) { // Yes: it has fired.
prevent_bust -= 2; // Avoid further action.
// Get a 'No Content' status which keeps us on the same page.
window.top.location = 'http://vadremix.com/204.php';
}
}, 1);
function clear ()
{
clearInterval(interval_id);
}
window.onload="setTimeout(clear (), 1000)";
After 1 second I want to clear the interval set earlier. This isn't working. How would I do what I'm trying to do?
If you substitute the last line with window.onload = function() { setTimeout(clear, 1000); }, it should do OK.
There are two errors in your code:
window.onload should be a function, rather than a string ("..."),
setTimeout accepts a function (clear), rather than the result from the function (clear())
By the way, these are some good places to learn JavaScript:
QuirksMode
Mozilla Developer Network
I have a function that updates a <div /> via AJAX:
function update() {
<!-- .ajax() -->
setTimeout(update(), 3000);}
}
What I need is that this is not executed when the user is not present on the website, so if there is no movement of the mouse (we will suppose that if move it is in the website) it will not update .mousemove(). By the way, there is any other thing that we can do to know is someone is active on the website?
How can this be done? Thank you in advance!
Edit: probably I explained bad. I need to know the way to only update when there is activity. Like Facebook does with his news feed, the front page. Thanks!
You could use a mousemove handler to track when the user last moved, and then have the process only happen if they last moved the mouse within X seconds. But of course, if the user is sitting there reading something, or if they're a keyboard-oriented kind of person, that will tend to miss that they are there... So you'd probably want to look at keydown as well.
Here's a mousemove example:
jQuery(function($) {
var count = 0, lastmove = new Date();
$(document).mousemove(function() {
++count;
lastmove = new Date();
$('#display').html("Moved " + count + " times");
});
});
Then your update code could do this:
function update() {
if (new Date() - lastmove < 60000) { // 60 seconds
// Really do the update
}
else {
// Check back in a few seconds
setTimeout(update, 3000);
}
}
Off-topic, but you have an error in your update code. You have:
setTimeout(update(), 3000);
...which will call update immediately and then try to use its return value to schedule something to happen in three seconds. If you want the call to update to be scheduled to happen in three seconds, leave off the () after it:
setTimeout(update, 3000);
I think I might have ended up with something such as this. Avoids date arithmetic. Only cares whether there's been some activity since the last update().
window.activeFlag = false;
window.updateDelay = 3000;
$(document).bind('mousemove scroll keydown', function(){ activeFlag = true; });
function update() {
if(activeFlag) {
doWork();
activeFlag = false;
}
}
window.setTimeout(update, updateDelay);
edit: I've discovered a flaw in the code. The following is more appropriate:
window.activeFlag = false;
window.updateDelay = 3000;
$(document).bind('mousemove scroll keydown', function(){ activeFlag = true; });
function update() {
if(activeFlag) {
doWork();
activeFlag = false;
}
window.setTimeout(update, updateDelay);
}
update();
I think there is no easy way to determine if the user is present
I would use a combination of mousemove, scroll, keypress.
var bUpdate = false;
function update() {
if(bUpdate){
///perform your ajax request
}
}
$(document).mousemove(function(){
bUpdate = true;
setTimeout(function(){bUpdate=false;}, 3000);}
});