Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-tab support using localStorage #49

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ Default: `false`

If `true`, this will launch the Bootstrap warning dialog / redirect (or callback functions) in a set amounts of time regardless of user activity. This in turn makes the plugin act much like the [jquery-sessionTimeout-bootstrap by maxfierke](https://github.com/maxfierke/jquery-sessionTimeout-bootstrap) plugin.

**clearWarningOnUserActivity**

Type: `Boolean`

Default: `true`

If `true` and `ignoreUserActivity === true`, when user activity is detected on the page during the warning period, the warning dialog will be dismissed. Otherwise, the warning dialog will remain on the page until the user either selects an option or is logged out due to inactivity.

**countdownSmart**

Type: `Boolean`
Expand Down Expand Up @@ -188,6 +196,14 @@ Default: `false`

Custom callback you can use instead of redirecting the user to `redirUrl`. Takes options object as the only argument.

**useLocalStorageSynchronization**

Type: `Boolean`

Default: false

Enables cross-tab synchronization to prevent inactive tabs from logging users out during periods of activity in other tabs. The `localStorageSynchronizationKey` option can be customized to change the storage key used (default: `sessionkeepalive__lastkeepalive`).

## Examples

You can play around with the examples in the `/examples` directory.
Expand All @@ -204,7 +220,8 @@ $.sessionTimeout({
logoutUrl: 'login.html',
redirUrl: 'locked.html',
warnAfter: 60000,
redirAfter: 120000
redirAfter: 120000,
useLocalStorageSynchronization: true // ensure multiple tabs do not conflict with one another
});
```

Expand Down
52 changes: 42 additions & 10 deletions dist/bootstrap-session-timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
keepAliveInterval: 5000,
keepAlive: true,
ignoreUserActivity: false,
clearWarningOnUserActivity: true,
onStart: false,
onWarn: false,
onRedir: false,
countdownMessage: false,
countdownBar: false,
countdownSmart: false
countdownSmart: false,
useLocalStorageSynchronization: false,
localStorageSynchronizationKey: "sessionkeepalive__lastkeepalive"
};

var opt = defaults,
Expand Down Expand Up @@ -109,18 +112,23 @@

// If they moved the mouse not only reset the counter
// but remove the modal too!
if ($('#session-timeout-dialog').length > 0 &&
$('#session-timeout-dialog').data('bs.modal') &&
$('#session-timeout-dialog').data('bs.modal').isShown) {
// http://stackoverflow.com/questions/11519660/twitter-bootstrap-modal-backdrop-doesnt-disappear
$('#session-timeout-dialog').modal('hide');
$('body').removeClass('modal-open');
$('div.modal-backdrop').remove();

if (opt.clearWarningOnUserActivity && modalIsDisplayed()) {
removeWarningModal();
}
});
}

function modalIsDisplayed() {
return $('#session-timeout-dialog').is(':visible');
}

function removeWarningModal() {
// http://stackoverflow.com/questions/11519660/twitter-bootstrap-modal-backdrop-doesnt-disappear
$('#session-timeout-dialog').modal('hide');
$('body').removeClass('modal-open');
$('div.modal-backdrop').remove();
}

// Keeps the server side connection live, by pingin url set in keepAliveUrl option.
// KeepAlivePinged is a helper var to ensure the functionality of the keepAliveInterval option
var keepAlivePinged = false;
Expand All @@ -134,6 +142,11 @@
data: opt.ajaxData
});
keepAlivePinged = true;

if (opt.useLocalStorageSynchronization) {
refreshLastKeepAliveSynchronizationValue();
}

setTimeout(function() {
keepAlivePinged = false;
}, opt.keepAliveInterval);
Expand Down Expand Up @@ -172,7 +185,7 @@
function startDialogTimer() {
// Clear session timer
clearTimeout(timer);
if (!$('#session-timeout-dialog').hasClass('in') && (opt.countdownMessage || opt.countdownBar)) {
if (!modalIsDisplayed() && (opt.countdownMessage || opt.countdownBar)) {
// If warning dialog is not already open and either opt.countdownMessage
// or opt.countdownBar are set start countdown
startCountdownTimer('dialog', true);
Expand All @@ -188,6 +201,21 @@
}, (opt.redirAfter - opt.warnAfter));
}

function refreshLastKeepAliveSynchronizationValue() {
localStorage.setItem(opt.localStorageSynchronizationKey, new Date());
}

function setupLocalStorageEventObservation() {
window.addEventListener('storage', function (e) {
if (e.key === opt.localStorageSynchronizationKey) {
startSessionTimer();
if (modalIsDisplayed()) {
removeWarningModal();
}
}
}, );
}

function startCountdownTimer(type, reset) {
// Clear countdown timer
clearTimeout(countdown.timer);
Expand Down Expand Up @@ -238,5 +266,9 @@
// Start session timer
startSessionTimer();

if (opt.useLocalStorageSynchronization) {
setupLocalStorageEventObservation();
}

};
})(jQuery);