I am building a live bidding website using Php and Pusher. There is a countdown timer in the site.
If the timer goes below 15 secs and if someone bids for a auction, the timer is reset back to 15 again. I am using Pusher to update timer in all open browsers. When the timer reaches 0 a function is called to end the auction.
Here is the problem I am facing:
If someone bids when the timer is around 1 secs left, the timer is updated in the browser in which the bid occurred. But as Pusher takes around a second to update the other browsers, the timer ends on other computer and the function to end the auction is called.
Here is sample code on what I am currently doing:
var pusher = new Pusher('key');
channel = pusher.subscribe('wppa');
pusher.connection.bind('connected', function(){
});
channel.bind('bid_added_event', function(response) {
StreamedAuction.update(response, AuctionModel);
});
channel.bind('end_auction_event', function(response) {
StreamedAuction.end(response, AuctionModel);
});
channel.bind('update_timer_event', function(response){
StreamedAuction.updateEndDate(response, AuctionModel);
});
If someone bids and the timer is less than 15 updat_timer_event is called to update the timer in all channels.
If the timer reaches 0, the the end auction_event is called. The problem is if someone bids when timer is 1 sec, the auction is ended even before the update_timer_event is called.
I am wondering if there is a way in pusher where you could listen if the event is fired in all channels. If this is possible the I was thinking I could do something like:
if the event is fired in all browsers
then end the auction
else
reset the counter to 15 in all channels
as somebody bided and the auction ending event wasnt fired from
one of the channel
Please let me know if you require more details or code.
Thanks.
Related
I'm working on a private site with important data, and I want to log out any user who hasn't done anything for 10min (forgot the tab open in the background as an example). How can I do that, is just running an event listener to the mouse clicks with a timer is fine, or are there other better solutions for this?
This can be achieved by JavaScript only.
Since our web app can be open in multiple tab, so its better to store last activity of user in localStorage
First lets declare events which we consider as user activity and store time of user activity in localStorage
document.addEventListener("mousemove", () =>{
localStorage.setItem('lastActvity', new Date())
});
document.addEventListener("click", () =>{
localStorage.setItem('lastActvity', new Date())
});
Next lets create interval which will be checked on every given interval.
let timeInterval = setInterval(() => {
let lastAcivity = localStorage.getItem('lastActvity')
var diffMs = Math.abs(new Date(lastAcivity) - new Date()); // milliseconds between now & last activity
var seconds = Math.floor((diffMs/1000));
var minute = Math.floor((seconds/60));
console.log(seconds +' sec and '+minute+' min since last activity')
if(minute == 10){
console.log('No activity from last 10 minutes... Logging Out')
clearInterval(timeInterval)
//code for logout or anything...
}
},1000)
event listeners for mouse movement (not clicks), and event listeners for keyboard clicks as well should do the job.
Let's say you want to log out the user after 10mins of inactivity. Simply start a timer (for 10mins) the moment user logs in, every time the user makes any mouse movement or any keyboard clicks, use the event listener to reset the timer.
If there is no activity, after 10mins, the timer should execute log out functionality.
Update :
Like the case suggested by Vishnu Bhadoriya, in that case, the idle solution should be to implement a heartbeat b/w the client and the server. Now, in this case, your mouse and keyboard listeners would send a lifeline event to the server, and the server will keep its session alive. When the lifeline event is not received by the server for more than 10mins (threshold for activity), the server can emit an event to the client which can log him out or can simple invalidate the client's auth token
I'm working on a small project, that combines Java(servlets) with some web elements. I've got a Java back-end that deals with registration and login. When the user has logged in, he/she arrives at the dashboard where a timer awaits them.
The timer should be set at 25 minutes and when the user presses 'start', it should start counting down to zero. When zero has been reached, I want the timer to save the timestamps (begin/end) to MySQL and automatically start a 5 minute timer.
I've been looking on Google for quite some time. jQuery seems the easiest option, but I'm genuinely struggling getting this started.
Is there anyone who could help me?
Perhaps guide me on the right path or (if you have time) have a little coding session?
On waiting page use Javascript:
var timeleft = 1500; // seconds left
var timer = setInterval(function () {
timeleft--;
// optional: update HTML element here
if (timeleft == 0) { saveTimestamp(); clearInterval(timer); }
}, 1000); // run every second
Then make saveTimestamp function either redirect browser to another page or make ajax call to sync with server.
On server, make a check if user reached this point after less than 25 minutes, and if he didn't (no cheating), perform standard writing to SQL (I can't help you much with server-side, as I've never worked with Java servlets).
I have a jQuery Mobile web app which targets iOS and Android devices. A component of the application is a background task, which periodically checks for a.) changes to local data and b.) connectivity to the server. If both are true, the task pushes the changes.
I'm using a simple setTimeout()-based function to execute this task. Each failure or success condition calls setTimeout() on the background task, ensuring that it runs on 30 second intervals. I update a status div with the timestamp of the last task runtime for debugging purposes.
In any desktop browser, this works just fine; however, on iOS or Android, after some period of time, the task stops executing. I'm wondering if this is related to the power conservation settings of the devices--when iOS enters stand-by, does it terminate JavaScript execution? That is what appears to happen.
If so, what is the best way to resume? Is there an on-wake event which I can hook into? If not, what other options are there which don't involve hooking into events dependent on user interaction (I don't want to bind the entire page to a click event just to restart the background task).
Looks like Javascript execution is paused on MobileSafari when the browser page isn't focused. It also seems if setInterval() events are late, they are simply fired as soon as the browser is focused. This means we should be able to keep a setInterval() running, and assume the browser lost/regained focus if the setInterval function took much longer than usual.
This code alerts after switching back from a browser tab, after switching back from another app, and after resuming from sleep. If you set your threshold a bit longer than your setTimeout(), you can assume your timeout wouldn't finish if this fires.
If you wanted to stay on the safe side: you could save your timeout ID (returned by setTimeout) and set this to a shorter threshold than your timeout, then run clearTimeout() and setTimeout() again if this fires.
<script type="text/javascript">
var lastCheck = 0;
function sleepCheck() {
var now = new Date().getTime();
var diff = now - lastCheck;
if (diff > 3000) {
alert('took ' + diff + 'ms');
}
lastCheck = now;
}
window.onload = function() {
lastCheck = new Date().getTime();
setInterval(sleepCheck, 1000);
}
</script>
Edit: It appears this can sometimes trigger more than once in a row on resume, so you'd need to handle that somehow. (After letting my android browser sleep all night, it woke up to two alert()s. I bet Javascript got resumed at some arbitrary time before fully sleeping.)
I tested on Android 2.2 and the latest iOS - they both alert as soon as you resume from sleep.
When the user switches to another app or the screen sleeps, timers seem to pause until the user switches back to the app (or when the screen awakens).
Phonegap has a resume event you can listen to instead of polling for state (as well as a pause event if you want to do things before it is out of focus). You start listening to it after deviceReady fires.
document.addEventListener("deviceready", function () {
// do something when the app awakens
document.addEventListener('resume', function () {
// re-create a timer.
// ...
}, false);
}, false);
I use angular with phonegap and I have a service implemented that manages a certain timeout for me but basically you could create an object that sets the timer, cancels the timer and most importantly, updates the timer (update is what is called during the 'resume' event).
In angular I have a scopes and root scope that I can attach data to, my timeout is global so I attach it to root scope but for the purpose of this example, I'll simply attach it to the document object. I don't condone that because you need should apply it to some sort of scope or namespace.
var timeoutManager = function () {
return {
setTimer: function (expiresMsecs) {
document.timerData = {
timerId: setTimeout(function () {
timeoutCallback();
},
expiresMsecs),
totalDurationMsecs: expiresMsecs,
expirationDate: new Date(Date.now() += expiresMsecs)
};
},
updateTimer: function () {
if (document.timerData) {
//
// Calculate the msecs remaining so it can be used to set a new timer.
//
var timerMsecs = document.timerData.expirationDate - new Date();
//
// Kill the previous timer because a new one needs to be set or the callback
// needs to be fired.
//
this.cancelTimer();
if (timerMsecs > 0) {
this.setTimer(timerMsecs);
} else {
timeoutCallback();
}
}
},
cancelTimer: function () {
if (document.timerData && document.timerData.timerId) {
clearTimeout(document.timerData.timerId);
document.timerData = null;
}
}
};
};
You could have the manager function take a millisecond parameter instead of passing it into set, but again this is modeled somewhat after the angular service I wrote. The operations should be clear and concise enough to do something with them and add them to your own app.
var timeoutCallback = function () { console.log('timer fired!'); };
var manager = timeoutManager();
manager.setTimer(20000);
You will want to update the timer once you get the resume event in your event listener, like so:
// do something when the app awakens
document.addEventListener('resume', function () {
var manager = timeoutManager();
manager.updateTimer();
}, false);
The timeout manager also has cancelTimer() which can be used to kill the timer at any time.
You can use this class github.com/mustafah/background-timer based on #jlafay answer , where you can use as follow:
coffeescript
timer = new BackgroundTimer 10 * 1000, ->
# This callback will be called after 10 seconds
console.log 'finished'
timer.enableTicking 1000, (remaining) ->
# This callback will get called every second (1000 millisecond) till the timer ends
console.log remaining
timer.start()
javascript
timer = new BackgroundTimer(10 * 1000, function() {
// This callback will be called after 10 seconds
console.log("finished");
});
timer.enableTicking(1000, function(remaining) {
// This callback will get called every second (1000 millisecond) till the timer ends
console.log(remaining);
});
timer.start();
Hope it helps, Thank you ...
You should use the Page Visibility API (MDN) which is supported just about everywhere. It can detect if a page or tab has become visible again and you can then resume your timeouts or carry out some actions.
I have used a few of the jquery keepalive session plugins with out problem.
I have been asked for something a bit different.
We have some forms (built before I started here) that are fairly large and users work in them for a while. The page is never refreshed, so they click save and the session is expired and redirect to the login page.
I suggested one of these plugin, that just prompt the user a few minutes before the session expires which would make an ajax call to keep the session alive.
However, they said, will what if they dont see the prompt and miss it all together and logs them out.
They would like me to check
Has the user had any interaction with the page in the last 5 minutes.
If Yes=Ajax call to keep alive the session, and reset timer.
if No, continue to wait until we get within 2 minutes of session time out and prompt user.
They are trying to avoid the prompt.
Is there anyway with JS/Jquery to know if the page has had any client side interaction?
Rather than using a timer to check if they've had any interaction in the last 5 minutes, couldn't you just send your keepalive any time the form has changed? It would eliminate a need for a timer loop and a small payload ajax call just to keep the session alive shouldn't hurt performance at all.
If you still want to keep the timer loop, I would still recommend using the change event on your form elements. Changing the form implies they're interacting with it, and I think that satisfies their requirement.
Edit: Update to use timer
var idle = true;
function finalIdleCheck(prompt){
if(idle){
if(prompt){
alert("last warning!");
}
//Tighten the idle check time loop; may even want to go < 30s
setTimeout(finalIdleCheck, 30*1000);
} else {
//Ajax stuff to keep session alive
idle = true; //Reset idle flag
}
}
function checkIdle(){
if(idle){
//Warn them
alert("You've been idle");
setTimeout(function(){
finalIdleCheck(true);
}, 60*2*1000);
} else {
//Ajax stuff to keep session alive
idle = true; //Reset idle flag
}
}
$(document).ready(function(){
$("form input").on("change", function(){
idle = false;
}
setTimeout(idleCheck, 60*5*1000);
}
I've got a field A in my webpage which, when edited by the user, invokes an API call (using jQuery), which updates field B. After the edit, the API should be called every 10 seconds to update the field B again. I currently do this using:
setTimeout(thisFunction, 10000);
The problem is that this timeout is set every time the user edits field A, which after editing field A a couple times causes the timeout to be set multiple times and the API to be called many many times. This makes the website look pretty stressy.
What I would rather like to do, is set a new timeout every time the field is edited, be it either by the user editing field A, or by the interval reaching 10 seconds and thereby polling the API. In other words; the field should be updated if field B wasn't updated for 10 or more seconds.
Lastly, if the user then clicks button C, the polling should stop.
So my question; how can I run a function to update field B if that field B wasn't updated for 10 or more seconds and how do I stop the polling when I want to (when the user clicks another button) All tips are welcome!
A timer can be cancelled with clearTimeout, so:
var timer = null;
if (timer) {
clearTimeout(timer); //cancel the previous timer.
timer = null;
}
timer = setTimeout(thisFunction, 10000);
var update;
// something happened
clearTimeout(update);
update = setTimeout(thisFunction, 10000);