diff --git a/session_security/static/session_security/script.js b/session_security/static/session_security/script.js index a9bef38..7a75966 100644 --- a/session_security/static/session_security/script.js +++ b/session_security/static/session_security/script.js @@ -26,6 +26,9 @@ yourlabs.SessionSecurity = function(options) { // Events that would trigger an activity this.events = ['mousemove', 'scroll', 'keyup', 'click', 'touchstart', 'touchend', 'touchmove']; + // Set a default counter element + this.counterElementID = 'session_security_counter' + // Merge the options dict here. $.extend(this, options); @@ -60,7 +63,7 @@ yourlabs.SessionSecurity.prototype = { window.location.reload(); } }, - + // Called when there has been no activity for more than warnAfter // seconds. showWarning: function() { @@ -68,7 +71,7 @@ yourlabs.SessionSecurity.prototype = { this.$warning.attr('aria-hidden', 'false'); $('.session_security_modal').focus(); }, - + // Called to hide the warning, for example if there has been activity on // the server side - in another browser tab. hideWarning: function() { @@ -87,11 +90,11 @@ yourlabs.SessionSecurity.prototype = { this.lastActivity = now; if (idleFor >= this.expireAfter) { - // Enforces checking whether a user's session is expired. This - // ensures a user being redirected instead of waiting until nextPing. + // Enforces checking whether a user's session is expired. This + // ensures a user being redirected instead of waiting until nextPing. this.expire(); } - + if (this.$warning.is(':visible')) { // Inform the server that the user came back manually, this should // block other browser tabs from expiring. @@ -130,16 +133,21 @@ yourlabs.SessionSecurity.prototype = { apply: function() { // Cancel timeout if any, since we're going to make our own clearTimeout(this.timeout); - var idleFor = Math.floor((new Date() - this.lastActivity) / 1000); if (idleFor >= this.expireAfter) { return this.expire(); } else if (idleFor >= this.warnAfter) { + if (!this.counterStarted && this.counterElementID){ + this.startCounter(); + } this.showWarning(); nextPing = this.expireAfter - idleFor; } else { this.hideWarning(); + if (this.counterStarted && this.counterElementID){ + this.stopCounter(); + } nextPing = this.warnAfter - idleFor; } @@ -149,6 +157,36 @@ yourlabs.SessionSecurity.prototype = { this.timeout = setTimeout($.proxy(this.ping, this), milliseconds); }, + startCounter: function(){ + let expireAfter = this.expireAfter; + let warnAfter = this.warnAfter; + let defaultTimeLeft = expireAfter - warnAfter; + let elementTarget = this.counterElementID; + let counterStarted = false; + if (!this.counterStarted) { + document.getElementById(elementTarget).innerHTML = defaultTimeLeft.toString(); + counterStarted = true; + } + var t = new Date(); + t.setSeconds(t.getSeconds() + defaultTimeLeft); + this.counterTimeout = setInterval(function() { + var now = new Date().getTime(); + var distance = t - now; + var seconds = Math.floor((distance % (1000 * expireAfter)) / 1000); + if (distance > 0) { + document.getElementById(elementTarget).innerHTML = seconds.toString(); + } + }, 1000); + this.counterStarted = counterStarted; + }, + + stopCounter: function(){ + clearTimeout(this.counterTimeout); + this.counterStarted = false; + let defaultTimeLeft = this.expireAfter - this.warnAfter; + document.getElementById(this.counterElementID).innerHTML = defaultTimeLeft.toString(); + }, + // onbeforeunload handler. onbeforeunload: function(e) { if ($('form[data-dirty]').length && !this.expired) { diff --git a/session_security/templates/session_security/dialog.html b/session_security/templates/session_security/dialog.html index 5e1a5fb..7095608 100644 --- a/session_security/templates/session_security/dialog.html +++ b/session_security/templates/session_security/dialog.html @@ -3,7 +3,7 @@