我一直在尝试集成jquery-idle-timeout-plugin来显示当用户空闲一段时间时会话超时弹出警告。
除了浏览器的新标签之外,一切正常。当我移动到新选项卡或其他选项卡然后或任何回发后,会话变为活动并重新设置该特定选项卡的计时器,但不重新设置其他选项卡或页面的计时器。
请查看以下代码
<script type="text/javascript">
var idleTime = 12000; // number of miliseconds until the user is considered idle
var initialSessionTimeoutMessage = 'Your session will expire in <span id="sessionTimeoutCountdown"></span> seconds.<br/><br />Click on <b>OK</b> to continue your session.';
var sessionTimeoutCountdownId = 'sessionTimeoutCountdown';
var redirectAfter = 10; // number of seconds to wait before redirecting the user
var path = getPath();
var redirectTo = "logout.aspx";
var keepAliveURL = 'Default.aspx'; // URL to call to keep the session alive
var expiredMessage = 'Your session has expired. You are being logged out for security reasons.'; // message to show user when the countdown reaches 0
var running = false; // var to check if the countdown is running
var timer; // reference to the setInterval timer so it can be stopped
$(document).ready(function () {
var path = window.location.pathname;
var file = path.split('/')[1];
if (file == 'Login.aspx') {
return;
}
// create the warning window and set autoOpen to false
var sessionTimeoutWarningDialog = $("#sessionTimeoutWarning");
$(sessionTimeoutWarningDialog).html(initialSessionTimeoutMessage);
$(sessionTimeoutWarningDialog).dialog({
title: 'Session Expiration Warning',
autoOpen: false, // set this to false so we can manually open it
closeOnEscape: false,
draggable: false,
width: 460,
minHeight: 50,
modal: true,
beforeclose: function () { // bind to beforeclose so if the user clicks on the "X" or escape to close the dialog, it will work too
// stop the timer
clearInterval(timer);
// stop countdown
running = false;
// ajax call to keep the server-side session alive
$.ajax({
url: keepAliveURL,
async: true
});
},
buttons: {
OK: function () {
// close dialog
$(this).dialog('close');
}
},
resizable: false,
open: function () {
// scrollbar fix for IE
$('body').css('overflow', 'hidden');
},
close: function () {
// reset overflow
$('body').css('overflow', 'auto');
}
}); // end of dialog
// start the idle timer
$.idleTimer(idleTime);
// bind to idleTimer's idle.idleTimer event
$(document).bind("idle.idleTimer", function () {
// if the user is idle and a countdown isn't already running
if ($.data(document, 'idleTimer') === 'idle' && !running) {
var counter = redirectAfter;
running = true;
// intialisze timer
$('#' + sessionTimeoutCountdownId).html(redirectAfter);
// open dialog
$(sessionTimeoutWarningDialog).dialog('open');
// create a timer that runs every second
timer = setInterval(function () {
counter -= 1;
// if the counter is 0, redirect the user
if (counter == 0) {
$(sessionTimeoutWarningDialog).html(expiredMessage);
$(sessionTimeoutWarningDialog).dialog('disable');
window.location = redirectTo;
} else {
$('#' + sessionTimeoutCountdownId).html(counter);
};
}, 1000);
};
});
});
</script>
请告诉我如何解决其他标签的问题(同步所有页面的计时器)
由于
答案 0 :(得分:3)
我明白了你的观点,使用jQuery的Idle超时插件只是识别它没有与多个选项卡或窗口选项集成的超时。但你可以像下面那样以一种棘手的方式实现这一目标。
jQuery(window).blur(function(){
//your code here to stop the finding idle time check
});
jQuery(window).focus(function(){
//your code here to start idle time check
});
请参阅:http://www.walkswithme.net/idle-timeout-plugin-using-jquery
答案 1 :(得分:3)
您的空闲计时器可以跨多个窗口进行通信(保持同步)。使用localStorage变量的选项卡。在github上,marcuswestin / store.js提供了多种浏览器类型的良好功能。请注意,某些浏览器/设备不支持localStorage,但大多数现代浏览器都支持localStorage。
这是idleTimer插件的'测试'代码,它提供了同步窗口和放大器。标签,只要它们都在同一个域中。它设置了2个localStorage变量,idleTimerLastActivity&amp; idleTimerLoggedOut,用于跟踪用户会话的“状态”。
演示页面。打开多个窗口/标签,您可以看到它是如何工作的。 http://jillelaine.github.io/jquery-idleTimeout/
/**
* This work is licensed under the MIT License
*
* Configurable idle (no activity) timer and logout redirect for jQuery.
* Works across multiple windows, tabs and iframes from the same domain.
*
* Dependencies: JQuery v1.7+, JQuery UI, store.js from https://github.com/marcuswestin/store.js - v1.3.4+
*
* Commented and console logged for debugging with Firefox & Firebug or similar
* version 1.0.6
**/
/*global jQuery: false, document: false, store: false, clearInterval: false, setInterval: false, setTimeout: false, window: false, alert: false, console: false*/
/*jslint indent: 2, sloppy: true, plusplus: true*/
(function ($) {
$.fn.idleTimeout = function (options) {
console.log('start');
//##############################
//## Configuration Variables
//##############################
var defaults = {
idleTimeLimit: 30000, // 30 seconds for testing. 'No activity' time limit in milliseconds. 1200000 = 20 Minutes
dialogDisplayLimit: 20000, // 20 seconds for testing. Time to display the warning dialog before redirect (and optional callback) in milliseconds. 180000 = 3 Minutes
redirectUrl: '/logout', // redirect to this url on timeout logout. Set to "redirectUrl: false" to disable redirect
// optional custom callback to perform before redirect
customCallback: false, // set to false for no customCallback
// customCallback: function () { // define optional custom js function
// perform custom action before logout
// },
// configure which activity events to detect
// http://www.quirksmode.org/dom/events/
// https://developer.mozilla.org/en-US/docs/Web/Reference/Events
activityEvents: 'click keypress scroll wheel mousewheel', // separate each event with a space
//dialog box configuration
dialogTitle: 'Session Expiration Warning',
dialogText: 'Because you have been inactive, your session is about to expire.',
// server-side session keep-alive timer
sessionKeepAliveTimer: 600000 // Ping the server at this interval in milliseconds. 600000 = 10 Minutes
// sessionKeepAliveTimer: false // Set to false to disable pings
},
//##############################
//## Private Variables
//##############################
opts = $.extend(defaults, options),
checkHeartbeat = 2000, // frequency to check for timeouts - 2000 = 2 seconds
origTitle = document.title, // save original browser title
sessionKeepAliveUrl = window.location.href, // set URL to ping to user's current window
keepSessionAlive, activityDetector,
idleTimer, remainingTimer, checkIdleTimeout, idleTimerLastActivity, startIdleTimer, stopIdleTimer,
openWarningDialog, dialogTimer, checkDialogTimeout, startDialogTimer, stopDialogTimer, isDialogOpen, destroyWarningDialog,
countdownDisplay, logoutUser,
checkForIframes, includeIframes, attachEventIframe; // iframe functionality
//##############################
//## Private Functions
//##############################
keepSessionAlive = function () {
if (opts.sessionKeepAliveTimer) {
var keepSession = function () {
if (idleTimerLastActivity === store.get('idleTimerLastActivity')) {
console.log('keep session alive function');
$.get(sessionKeepAliveUrl);
}
};
setInterval(keepSession, opts.sessionKeepAliveTimer);
}
};
activityDetector = function () {
$('body').on(opts.activityEvents, function () {
if (isDialogOpen() !== true) {
console.log('activity detected');
startIdleTimer();
} else {
console.log('dialog open. activity ignored');
}
});
};
checkIdleTimeout = function () {
var timeNow = $.now(), timeIdleTimeout = (store.get('idleTimerLastActivity') + opts.idleTimeLimit);
if (timeNow > timeIdleTimeout) {
console.log('timeNow: ' + timeNow + ' > idle ' + timeIdleTimeout);
if (isDialogOpen() !== true) {
console.log('dialog is not open & will be opened');
openWarningDialog();
startDialogTimer();
}
} else if (store.get('idleTimerLoggedOut') === true) { //a 'manual' user logout?
logoutUser();
} else {
console.log('idle not yet timed out');
if (isDialogOpen() === true) {
console.log('dialog is open & will be closed');
destroyWarningDialog();
stopDialogTimer();
}
}
};
startIdleTimer = function () {
stopIdleTimer();
idleTimerLastActivity = $.now();
store.set('idleTimerLastActivity', idleTimerLastActivity);
console.log('start idle timer: ' + idleTimerLastActivity);
idleTimer = setInterval(checkIdleTimeout, checkHeartbeat);
};
stopIdleTimer = function () {
clearInterval(idleTimer);
};
openWarningDialog = function () {
var dialogContent = "<div id='idletimer_warning_dialog'><p>" + opts.dialogText + "</p><p style='display:inline'>Time remaining: <div style='display:inline' id='countdownDisplay'></div></p></div>";
$(dialogContent).dialog({
buttons: {
"Stay Logged In": function () {
console.log('Stay Logged In button clicked');
destroyWarningDialog();
stopDialogTimer();
startIdleTimer();
},
"Log Out Now": function () {
console.log('Log Out Now button clicked');
logoutUser();
}
},
closeOnEscape: false,
modal: true,
title: opts.dialogTitle
});
// hide the dialog's upper right corner "x" close button
$('.ui-dialog-titlebar-close').css('display', 'none');
// start the countdown display
countdownDisplay();
// change title bar to warning message
document.title = opts.dialogTitle;
};
checkDialogTimeout = function () {
var timeNow = $.now(), timeDialogTimeout = (store.get('idleTimerLastActivity') + opts.idleTimeLimit + opts.dialogDisplayLimit);
if ((timeNow > timeDialogTimeout) || (store.get('idleTimerLoggedOut') === true)) {
console.log('timeNow: ' + timeNow + ' > dialog' + timeDialogTimeout);
logoutUser();
} else {
console.log('dialog not yet timed out');
}
};
startDialogTimer = function () {
dialogTimer = setInterval(checkDialogTimeout, checkHeartbeat);
};
stopDialogTimer = function () {
clearInterval(dialogTimer);
clearInterval(remainingTimer);
};
isDialogOpen = function () {
var dialogOpen = $("#idletimer_warning_dialog").is(":visible");
if (dialogOpen === true) {
return true;
}
return false;
};
destroyWarningDialog = function () {
console.log('dialog destroyed');
$(".ui-dialog-content").dialog('destroy').remove();
document.title = origTitle;
};
// display remaining time on warning dialog
countdownDisplay = function () {
var dialogDisplaySeconds = opts.dialogDisplayLimit / 1000, mins, secs;
remainingTimer = setInterval(function () {
mins = Math.floor(dialogDisplaySeconds / 60); // minutes
if (mins < 10) { mins = '0' + mins; }
secs = dialogDisplaySeconds - (mins * 60); // seconds
if (secs < 10) { secs = '0' + secs; }
$('#countdownDisplay').html(mins + ':' + secs);
dialogDisplaySeconds -= 1;
}, 1000);
};
logoutUser = function () {
console.log('logout function');
store.set('idleTimerLoggedOut', true);
if (opts.customCallback) {
console.log('logout function custom callback');
opts.customCallback();
}
if (opts.redirectUrl) {
console.log('logout function redirect to URL');
window.location.href = opts.redirectUrl;
}
};
// document must be in readyState 'complete' before looking for iframes
checkForIframes = function () {
var docReadyCheck, isDocReady;
docReadyCheck = function () {
if (document.readyState === "complete") {
console.log('check for iframes, now that the document is complete');
clearInterval(isDocReady);
includeIframes();
}
};
isDocReady = setInterval(docReadyCheck, 1000);
};
// look for iframes
includeIframes = function () {
console.log('include iframes start');
var foundIframes = document.getElementsByTagName('iframe'), index, iframeItem;
if (foundIframes.length > 0) { //at least one iframe found
console.log('iframes found: ' + foundIframes.length);
// attach events to each iframe found
for (index = 0; index < foundIframes.length; index++) {
iframeItem = foundIframes.item(index);
if (iframeItem.attachEvent) { // IE < 11. Returns a boolean true/false
console.log('attach event to iframe. Browser IE < 11');
iframeItem.attachEvent('onload', attachEventIframe(index));
} else { // IE >= 11 and FF, etc.
console.log('attach event to iframe. Browser NOT IE < 11');
iframeItem.addEventListener('load', attachEventIframe(index), false);
}
} // end for loop
} // end if any iframes
};
// attach events to each iframe
attachEventIframe = function (index) {
var iframe = $('iframe:eq(' + index + ')').contents().find('html');
iframe.on(opts.activityEvents, function (event) {
console.log('bubbling iframe activity event to body of page');
$('body').trigger(event);
});
};
//###############################
// Build & Return the instance of the item as a plugin
// This is your construct.
//###############################
return this.each(function () {
if (store.enabled) {
idleTimerLastActivity = $.now();
store.set('idleTimerLastActivity', idleTimerLastActivity);
store.set('idleTimerLoggedOut', false);
} else {
alert('Please disable "Private Mode", or upgrade to a modern browser. Or perhaps a dependent file missing. Please see: https://github.com/marcuswestin/store.js');
}
activityDetector();
keepSessionAlive();
startIdleTimer();
checkForIframes();
});
};
}(jQuery));