jquery-idleTimeout
jquery-idleTimeout copied to clipboard
Detect activity on all tabs & windows within same site
If user has multiple open tabs or windows to the same site, inactivity on any of these open tabs/windows will 'idle timeout' for all open tabs/windows.
Modal warning popup does not appear on user's current tab/window, so user sees no warning.
Redirect to 'auto logout' page does not appear on current tab/window, so user has no notice of logout. Instead, 'logged in' features just quit working.
If possible, would be nice to detect activity on any open tabs/windows within the same site.
Or, at least have warning popup appear on user's current tab/window.
I am also experiencing this issue. It would be preferred for the plug-in to detect that there is activity in the other tab and not warn at all, since the user is actually active in the other tab.
If I had time, I would start integrating with this for cross-tab communication - http://theprivateland.com/bncconnector/index.htm
Does it make sense just to include a parameter named cookie that will accept the name of a cookie to use for the current domain in a way that before showing the auto-logout popup the cookie is checked and if still not expired then use its expiration as the time to wait before showing the popup? Of course after the popup times out a check should be done again just in case from another tab the session was extended. Local storage could be supported for new browsers as well.
Hi all, I figured out how to ensure a cross site updateable session state :-)
Update your Session Timeout value in your database or Session Var (however you manage state in your app) and on whatever pages you are opening / using across your app.
Use an alive_url page to write the current Session Timeout value in milliseconds as plain text and modify the two methods below to return and update the opts.inactivity value from the AJAX get request. This will allow all windows to share the current session timeout value !!
I currently load an iframe in one screen as a popup window. This in turn loads an iframe which loads in another long running scripted page. The problem I had was that I was updating script timeout and session timeout on both the iframe loaded pages, however the parent / bottom page was the one timing out due to not receiving the updated session timeout value in idleTimeout plugin.
var stay_logged_in = function(el) {
start_liveTimeout();
if(opts.alive_url) {
// $.get(opts.alive_url); // Original method !!
// RH Mod : 08/07/2013 - We'll update this periodically using a Session.Timeout written to our alive_url / update_session_status page !!
$.get(opts.alive_url, function(data) {
opts.inactivity = parseFloat(data);
});
}
}
var keep_session = function() {
// $.get(opts.alive_url); // Original method !!
// RH Mod : 08/07/2013 - We'll update this periodically using a Session.Timeout written to our alive_url / update_session_status page !!
$.get(opts.alive_url, function(data) {
opts.inactivity = parseFloat(data);
});
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(keep_session, opts.sessionAlive);
}
Hope this helps someone.
Richard Hetherington Web Developer Bournemouth, United Kingdom
P.s. I have read all your comments above and as I have benefited from this plugin, I will consider options to enhance this plugin to be fully cross site usable - however many tabs you have open and however many iframes you load on top of each other etc.
If / when I make any changes, I'll post them here for others to consider / comment on.
Richard Hetherington Web Developer Bournemouth, United Kingdom
Oops, I found a slight bug in my mods above. Here is the final code. It required the liveTimeout to be cleared and reset after updating the inactivity value from alive_url page.
//###### //## This work is licensed under the Creative Commons Attribution-Share Alike 3.0 //## United States License. To view a copy of this license, //## visit http://creativecommons.org/licenses/by-sa/3.0/us/ or send a letter //## to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. //######
(function($){ $.fn.idleTimeout = function(options) { var defaults = { inactivity: 1200000, // 20 Minutes noconfirm: 10000, // 10 Seconds sessionAlive: 30000, // 30 Seconds redirect_url: '/js_sandbox/', click_reset: true, alive_url: '/js_sandbox/', logout_url: '/js_sandbox/', showDialog: true, dialogTitle: 'Auto Logout', dialogText: 'You are about to be signed out due to inactivity.', dialogButton: 'Stay Logged In' }
//##############################
//## Private Variables
//##############################
var opts = $.extend(defaults, options);
var liveTimeout, confTimeout, sessionTimeout;
var modal = "<div id='modal_pop'><p>"+opts.dialogText+"</p></div>";
//##############################
//## Private Functions
//##############################
var start_liveTimeout = function() {
clearTimeout(liveTimeout);
liveTimeout = setTimeout(logout, opts.inactivity);
if(opts.sessionAlive) {
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(keep_session, opts.sessionAlive);
}
}
var logout = function() {
var my_dialog;
var buttonsOpts = {};
clearTimeout(confTimeout);
confTimeout = setTimeout(redirect, opts.noconfirm);
buttonsOpts[opts.dialogButton] = function() {
my_dialog.dialog('close');
stay_logged_in();
}
if ( opts.showDialog ) {
my_dialog = $(modal).dialog({
buttons: buttonsOpts,
modal: true,
title: opts.dialogButton
});
}
}
var redirect = function() {
if ( opts.logout_url ) {
$.get(opts.logout_url);
}
window.location.href = opts.redirect_url;
}
var stay_logged_in = function(el) {
start_liveTimeout();
if ( opts.alive_url ) {
// $.get(opts.alive_url); // Original method
// RH Mod : 08/07/2013
get_alive_url();
}
}
var keep_session = function() {
if ( opts.alive_url ) {
// $.get(opts.alive_url); // Original method
// RH Mod : 08/07/2013
get_alive_url();
}
// Loop
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(keep_session, opts.sessionAlive);
}
// RH Mod - New Private method : 08/07/2013 - We'll update this periodically using a Session.Timeout written to our alive_url / update_session_status page !!
var get_alive_url = function() {
$.get(opts.alive_url, function(data) {
// Only update if the value has changed !!
if ( opts.inactivity != parseFloat(data) ) {
// Update our inactivity value (milliseconds) !!
opts.inactivity = parseFloat(data);
// Reset our logout timeout - There's no point in updating opts.inactivity without updating the timeout call which uses it !!
clearTimeout(liveTimeout);
liveTimeout = setTimeout(logout, opts.inactivity);
}
});
}
//###############################
//Build & Return the instance of the item as a plugin
// This is basically your construct.
//###############################
return this.each(function() {
obj = $(this);
start_liveTimeout();
if ( opts.click_reset ) {
$(document).bind('click', start_liveTimeout);
}
if ( opts.sessionAlive ) {
keep_session();
}
});
}; })(jQuery);
I could not get this mod to work in Firefox v.22. The button on the modal dialog does not correctly close the dialog box: instead it builds dialog boxes on top of each other each time the button is clicked. (You can close the modal dialog box(es) with the x in the right corner.) And the session still times out on the oldest tab, as far as I could tell.
It was interesting to experiment with it, though. Thank you for trying!
I believe the correct way to handle this in all tabs should be pure front end driven. We have done it that way (using https://github.com/marcuswestin/store.js/).
** Nestor, very interesting - I'll have a look more into localstorage (html5). I've heavilly been using some of html5's new functionality, but not all of it. If only there were more hours in each day! Thanks for posting though.
** Jill, my original code above does work roughly, although it depends on your server model employed and how you manage state.
The code below is tried and tested in all current browsers that I could test with and simply relies on setting a server side cookie with an initial session timeout value in milliseconds for your desired user session timeout. You will need to create a function called getCookie() or use a jquery cookie plugin and update my getCookie() call to your own. I have provided mine below should you wish to use them.
Basically what I do is call idleTimeout on the parent / initial page and load everything else in iframes on top of it using colorbox jquery plugin. I pass a variable through with each iframe src attribute so that I know not to load idleTimeout on each child page of the parent loading page - this is the key!! By updating my session timeout cookie value server side on each child page the idleTimeout can read this cookie value every 30 seconds and compare it against the previous value. If it changes, then we update our inactivity value and reset our liveTimeout. I'm not sure this can be achieved using HTML5's localStorage as this is client side and we are using server side / client side co-operation here to prevent session timeouts!
I haven't started working on control of ui dialogs across tabs, windows, iframes etc, yet, but will be when time permits. Anyone with any free time, happy to hear from you.
The code below works for me and I have successfully had child and parent pages all stay logged in / active for several hours before timing out at the correct time and redirecting the user to my configured page.
Hopefully this will provide "food for thought".
Happy for any ideas to be posted for improvement :-)
Richard Hetherington
For the sake of versioning I will call the code below : jquery-idleTimeout_2013_07_10.js
//###### //## This work is licensed under the Creative Commons Attribution-Share Alike 3.0 //## United States License. To view a copy of this license, //## visit http://creativecommons.org/licenses/by-sa/3.0/us/ or send a letter //## to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. //######
(function($){ $.fn.idleTimeout = function(options) { var defaults = { inactivity: 1200000, // 20 Minutes noconfirm: 10000, // 10 Seconds sessionAlive: 30000, // 30 Seconds redirect_url: '/js_sandbox/', click_reset: true, alive_url: '/js_sandbox/', logout_url: '/js_sandbox/', showDialog: true, dialogTitle: 'Auto Logout', dialogText: 'You are about to be signed out due to inactivity.', dialogButton: 'Stay Logged In' }
//##############################
//## Private Variables
//##############################
var opts = $.extend(defaults, options);
var liveTimeout, confTimeout, sessionTimeout;
var modal = "<div id='modal_pop'><p>"+opts.dialogText+"</p></div>";
//##############################
//## Private Functions
//##############################
var start_liveTimeout = function() {
clearTimeout(liveTimeout);
liveTimeout = setTimeout(logout, opts.inactivity);
if ( opts.sessionAlive ) {
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(keep_session, opts.sessionAlive);
}
}
var logout = function() {
var my_dialog;
var buttonsOpts = {};
clearTimeout(confTimeout);
confTimeout = setTimeout(redirect, opts.noconfirm);
buttonsOpts[opts.dialogButton] = function() {
my_dialog.dialog('close');
stay_logged_in();
}
if ( opts.showDialog ) {
my_dialog = $(modal).dialog({
buttons: buttonsOpts,
modal: true,
title: opts.dialogButton
});
}
}
var redirect = function() {
// call logout url
if ( opts.logout_url ) {
$.get(opts.logout_url);
}
// redirect to url
window.location.href = opts.redirect_url;
}
var stay_logged_in = function(el) {
start_liveTimeout();
if ( opts.alive_url ) {
// RH Mod : 08/07/2013
get_alive_url();
}
}
var keep_session = function() {
if ( opts.alive_url ) {
// RH Mod : 08/07/2013
get_alive_url();
}
// Loop
clearTimeout(sessionTimeout);
sessionTimeout = setTimeout(keep_session, opts.sessionAlive);
}
// RH Mod - New Private method : 08/07/2013 - We'll update this periodically using a Session.Timeout written to our alive_url / update_session_status page !!
var get_alive_url = function() {
// We will update SessionTimeout in a cookie and check it for changes !!
// You will need to create a getCookie() function for this. You likely have one in your core js libraries
var new_inactivity = parseFloat( getCookie( "SessionTimeout" ) );
// Only update if the value has changed !!
if ( new_inactivity ) {
if ( new_inactivity != opts.inactivity ) {
// Update our inactivity value (milliseconds) !!
opts.inactivity = new_inactivity;
//alert("New Session Timeout: " + new_inactivity);
// Reset our logout timeout - There's no point in updating opts.inactivity without updating the timeout call which uses it !!
clearTimeout(liveTimeout);
liveTimeout = setTimeout(logout, opts.inactivity);
}
}
/*
THIS DOESN'T WORK IN IIS - Do Not Send ServerXMLHTTP or WinHTTP Requests to the Same Server.
If you monitor http requests in Firebug or Fiddler etc you will see that they hang waiting for an available thread or worker process to complete
http://support.microsoft.com/kb/316451
$.get(opts.alive_url, function(data) {
var new_inactivity = parseFloat(data);
// Only update if the value has changed !!
if ( new_inactivity ) {
if ( new_inactivity != opts.inactivity ) {
// Update our inactivity value (milliseconds) !!
opts.inactivity = new_inactivity;
// Reset our logout timeout - There's no point in updating opts.inactivity without updating the timeout call which uses it !!
clearTimeout(liveTimeout);
liveTimeout = setTimeout(logout, opts.inactivity);
}
}
});
*/
}
//###############################
//Build & Return the instance of the item as a plugin
// This is basically your construct.
//###############################
return this.each(function() {
obj = $(this);
if ( opts.click_reset ) {
$(document).bind('click', start_liveTimeout);
}
start_liveTimeout();
});
}; })(jQuery);
// Some cookie functions should you need them
function setCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function deleteCookie(name) {
setCookie(name,"",-1);
}
@rhetherington we have released a our modification (with @nestoru) to your code on another fork: https://github.com/josebalius/jquery-idleTimeout essentially we use store.js and sync the tabs by checking a localStorage property every time a specific tab times out. Take a look at the source I'm sure you'll be to see the line changes.
Here is a blog post talking about how to use it: http://passionengineering.blogspot.com/2013/07/enhancing-jquery-idletimeout-plugin-to.html I can do a pull request if you want to merge these changes and add a dependency to store.js (or create your own localStorage wrapper :) ).
Hey, - please submit a pull request, ill double test it an integrate it. - thanks, i havnt had much time recently to re-update the code.
Thanks to encouragement from others, I wrote a fork of josebalius' fork to allow cross browser communication and various configuration options, such as what activity to detect (click, keypress, etc).
https://github.com/JillElaine/jquery-idleTimeout
Functions across multiple instances of a browser and across multiple tabs in the same browser window
If active window or tab is logged out, all inactive windows and tabs will log out immediately.
If warning dialog pops up on active window or tab, warning dialog appears on all other windows and tabs too.
If 'Stay Logged In' button on warning dialog is clicked, warning dialogs on all other windows and tabs will close too.
hye,i got problem to use jquery-idleTimeout in my code. actually i got to access into 2 different virtual directory in same server http://serverABC/myMainApp. After user login then they will click into hyperlink to call htt://serverABC/my2ndApp carrying sharing same statesession SQLServer and will open in new tab
my problem is,while user active on 2nd tab,the first tab keep on checking timeout because of inactive,prompt message only show at first tab,i hope if possible to prompt it also at 2nd or other active tab.
can i have an example of apps that used your code for me to study, TQ
rahmanAi, look at a fork of this project that works with multiple tabs and windows https://github.com/JillElaine/jquery-idleTimeout
@rahmanAi i was just about to point you to the fork above - this project is basically dead/abandoned - I don't do much with jQuery any more, but @JillElaine and some others have really good forks, there is also another more robust plugin under a similar name floating out there that is much more robust at this point.
Thanks all! As mentioned, you should take a look at Jill's fork for the latest and greatest.