basically what i am doing is set a timer to logout the user after a hour has passed but only if the user is inactive so i want to restart the timer after user has did any activity (scroll, keypress, mousemove, click) the thing is that the timer doesn't reset or something else thats why in the logout function i want to know did the timer actually reset and thats why i want to know the time passed by the timer.
i am using javascript, any help pls?
If this is a "feature" -- sure use Javascript, but if security is your aim, use server side, no doubt about it.
It would be a big nuisance to have to code something to track every little change that could happen, scroll, click, focus, keypress, etc, to determine if the user was "idle" or not -- so it's an idea to use something like erichydns idleTimer, jquery plugin: http://www.erichynds.com/jquery/a-new-and-improved-jquery-idle-timeout-plugin/
edit: this would be more suitable for you: http://paulirish.com/2009/jquery-idletimer-plugin/
demo is available here which shows in real time if the user is "idle" or not http://paulirish.com/demo/idle-timer
You can clar the setTimeout using the following code:
var t = setTimeout(myFunction,100000);
clearTimeout(t); //clear the timeout
If you want to know how much time is left, then you have to count the seconds or so ;)
Related
I am making a browser game in html, css, and javascript, written in perl. Health and stamina are kept in the server and I use javascript to show the user a live updated count of these stats while the current page is loaded. This works fine, however if the user switches tabs or switches away from the browser and leaves it running in the background, the count value you see when you return does not keep up properly. So when you switch back to the browser, your counter might say 50/100 stamina when you actually have 100/100. So when you do something in the game (loads a new page) the server updates the counter to the true amount because the javascript is just keeping time to show the user a "live" rolling view in the browser.
Is there a way to ensure the javascript counter will continue to function even if the page/tab isn't active or on the forefront? Aside from completely re-writing my game to include continuous live server pushes in what is displayed on the browser to the user?
Say you are playing the game. You see your health and stamina regenerating. You switch to another program for a minute, then return to the game in the browser. You notice your health and stamina have not updated while you were away. But when you perform an action in the game, this value is updated to what it should be because it is tracked internally on the server. This is what I would like to fix. Hope that makes sense!
I have not tried anything to fix this issue yet besides searching the web and ending up on this site without a really "good" answer in sight, so I decided to ask the question.
Continuous server pushes wouldn't work either. Anything in the main event loop like a timer, or events happening when it's out of focus, gets slowed down by the browser to conserve resources. Some mobile browsers will stop it together.
The answer to the question is to change how your app keeps track of these stats.
Now some will say to use WebWorkers to run the timer in a separate thread but this won't solve all your issues. You'd still have a different version of the issue, like if someone restored your webpage from sleep or something along those lines. No background task can survive that.
You mention that you track these stats also on the server. That's convenient, so the most obvious thing you should do is detect when the tab comes back into focus using the Window focus event. You would then make all the calls to the server to fetch the most up-to-date stats and reset the timers based on that fresh data. To stop it from showing stale data while the request is in flight, you might choose to show a loading spinner or something during that period.
Another common way of fixing this is you keep around on each timer increment a var which says when the data last came back (a timestamp). When you leave focus, you detect this with the blur event and store that last timestamp somewhere. Then they come back into focus, you handle the focus event and calculate the difference between the current time and the last recorded time before defocus (blur). You may be able to recalculate from this period what the values should be.
But if your server has this info, it'd be far less error-prone and easy to just ask the server when they refocus.
I was curious if there was a way to detect the user pressing the "stop navigation" button in the browser using javascript (or, even better, jQuery.) For example, if you click a link for a webpage that takes a while to load, you may want to show a spinning loader. But what if the user cancels navigation to the page? Is there anyway to detect that to get rid of the spinning loader that you put?
EDIT: I did a bit more research, and there seems to be an onStop event in javascript but, wouldn't you know it, it only works in internet explorer. If anyone has any other ideas to implement a cross browser solution like onStop, that'd be wonderful, but if not, I'll answer my own question in a few days to close this.
EDIT 2: https://stackoverflow.com/a/16216193 says it's not possible. As do a few other answers.
Alright so, as promised, I'm going to answer my own question.
I've thought about this quite a bit - and I've come up with a solution. I wasn't able to make it work in code (I didn't try too hard), but it should work in theory.
So I thought about the criteria of deciding when a webpage should decide stop was called. I came up with this:
If the script hasn't died after a reasonable amount of time, it can be assumed navigation has been canceled.
Then a jQuery event can be fired on the body or something like that. But what constitutes "a resonable amount of time?" I figured it would be partially based on page render time (fetching images, etc.) to get an idea of how fast the user's internet is. That can be gotten by doing:
var start = new Date();
var time;
$("body").load(function () {
time = new Date() - start;
...
});
Multiply that by a coefficient (maybe 3 or something) and get an approxamate transfer time. (This would have to be adjusted to account for how long it would take for the server to generate the next page, dependent on how dynamic it is.) Then, using this new found time*3 you'd write something like this:
$("a").click(function() { //Anything that could go to another page should filter through here
setInterval(function() {$(document).trigger("navstopped");},time*3);
}
$(document).on("navstopped") {
//Do stuff now that we assume navigation stopped.
}
Assume. That's really all we're doing here. We may have an inconsistent internet connection, fast one minute, slow the next. Server load could be inconsistent too. Maybe it's serving up images like a ninja for this page, but it's hit with a bunch of requests the next, making it generate/serve the next page a bit slower. So we're just assuming that something interrupted the navigation some how, but we are not certain.
Now, of course, this could be used in conjunction with IE's onStop event, but this was really the only cross browser solution I could think of. I wasn't able to get it to work, but maybe some jQuery god may be able to in the future.
Edit before post: Even before I posted this, I had another idea. More browsers support onAbort. If we have a picture that never loads, and the user presses stop, will onAbort be fired? Even if another webpage is loading? It requires testing but that may work too. I like my first idea better though. Although unstable, it is more stable than this cockamamie idea and I realize this could be bad practice.
I've found variants of this problem on Stack Overflow but nothing my matches my specific circumstance. Hopefully someone has some insight.
Right now I'm working on a web application where there is a button (technically an anchor tag) that spawns a list of items when pressed. The issue is, if the user presses this button rapidly twice in a row, the list will be spawned twice-- the button is meant to clear the list before spawning it to prevent duplication, but something about the way the scripts interact is causing this bug. The button spawns the list by making an ajax call to a server.
Now, I've tried fixing this bug by flipping a boolean value to 1 when the button is pressed, and making the button do nothing until it is 0 again. This seems not to work regardless of where in the code I set the value to 0 again: I've tried putting it at the end of the ajaxGet function, as well as after page load, but neither solution works.
Ideally, I would like a way for the button to become enabled as soon as the page is completely finished loading and rendering. Ultimately, what's needed is a way of preventing the user from pressing the button twice in a row. I've considered using a timer for this, but I'd prefer not to have to resort to that.
Any ideas? Let me know if you would like code snippets.
===========================================
EDIT: Thanks everyone for your answers! I used a variant of Fibrewire's answer to solve the problem, and it works great. At the beginning of the method that the button calls, I put the following code:
if (actionsDisabled == 1) {
return;
}//if
else {
actionsDisabled = 1;
setTimeout("actionsDisabled=0;", 1000);
}//else
Where actionsDisabled is a global boolean. It might not be as airtight as it could be (in particular, you'd hit a problem if the list took more than a second to load), but it's elegant and functional, and has the added bonus of reducing server requests (if traffic ever became a problem, you could restrict calls to once every 5 or 10 seconds or whatever). Thanks again!
you can disable the button after the first click
Disabling the button after once click
and if you need the user to be able to click the button again in the future you can use the setTimeout() method to re enable it after a brief pause
http://www.w3schools.com/jsref/met_win_settimeout.asp
I've searched SO and this question seems to have been asked multiple times, but I can't seem to get it to work in my example.
Here's some code to play with:
http://jsfiddle.net/vol7ron/w8QsZ/2/
What I'm looking for is something similar to the to the flowplayer tooltip, where:
there's a trigger that causes the menu to appear when hovered
the menu disappears on leaving the trigger
if the user hovers over the menu (or tooltip), then the popup should stay open
My guess is that the trigger's hoverOut should call the disappear using setTimeout() with some delay, but on the menu's mouseenter(), the timeout should be cleared.
I'm still new to jQuery and am unsure where to store the generated timeoutID and where to call it.
Note: the same menu will be used for multiple triggers.
Update: Okay, I have something working: here
Could someone please help me clean it up and make it more efficient. More importantly, I would like not to use globals for the timeoutID. Perhaps there's a better way to store it in the object?
I just did something like this recently. What I would do is
var timer = setTimeout(/*blah*/);
$('#my_selector').data('timer') = timer;
I throw the timeoutID in the data for that element and then whenever I need to do something with it later (clearTimeout) I can just grab it from there.
note I used this method and it worked for a dynamic amount of elements, which is what I think you want. Just let me know if you need more of an explanation!
I am in the midst of working on a project that is session-based. I was thinking that similar to a bank, I'd create a check and offer users the ability to thwart a session time-out.
I was thinking about creating a setInterval that would check a blank page that requires auth. If the timer is getting close to end-times, it'd throw up a dialogue advising the user that session is near end. A 'stay logged in' button would reset the timer, and they'd also be presented with an option to log off. If the set interval gets a '401' from the checker page, the current page would be refreshed to the login screen.
Does this make sense? Would the setInterval bog down the browser?
As an aside: what is the easiest way to clearInterval based on user interaction? Would I need to check for every keypress, and/or mouse event? Or is there a broader way of checking if the user is interacting with the page (like a focus check or something)?
Tanka.
So, I had some problems with the framework I'm using.. The session handling is not very good, therefore there seemed to be a problem with updating the session timout instead of having it timeout always based on the time since login, as opposed to since last activity. Anyway, got that handled. The issue I'm wondering about now is that by checking to see if the session is still authenticated via setInterval, the session will be updated via the check, therefore the session will never timeout. Or, am I missing something?
I decided to handle it just with javascript. Set the timeout to never in the framework config, and am handling timeouts with setTimeout exclusively.
function alerter(msg){
//warn user session about to expire; give opportunity to save
}
function killSess(){
window.location = '/logout';
}
function sessTimer(time){
timerID = window.setTimeout('killSess();',time);
}
function observe(div){
Event.observe(div, 'click', function(){
clearTimeout(timerID);
sessTimer(30000);
});
Event.observe('bodyDiv', 'keydown', function(e){
clearTimeout(timerID);
sessTimer(30000);
});
}
Does this make sense? Would the
setInterval bog down the browser?
This should work fine. So long as the interval is fairly large (a few seconds to a minute) and does not increase the size of a global data structure with each iteration, I don't anticipate it bogging down the browser.
As an aside: what is the easiest way
to clearInterval based on user
interaction? Would I need to check for
every keypress, and/or mouse event? Or
is there a broader way of checking if
the user is interacting with the page
(like a focus check or something)?
Maybe adding a few event handlers to a top-level page element such as a container div might be helpful.
It makes perfect sense, and setInterval wouldn't bog down the browser, as long as you make sure not to register it once more when it's already registered.
You only want to run clearInterval on the click of one specific button ("no, don't poll the browser", or "log out"), so i don't quite see the problem in your last paragraph...?
Other than that, I'll just add that upon 401, you shouldn't refresh to login screen. Just notify the user that the session seems to have been lost, so that the user can decide on his own to save anything he might be working with, or perhaps to log in again in a new tab.