Merge branch 'devel'
[qcg-portal.git] / better_sessions / static / better_sessions / better_sessions.js
diff --git a/better_sessions/static/better_sessions/better_sessions.js b/better_sessions/static/better_sessions/better_sessions.js
new file mode 100644 (file)
index 0000000..e6979cb
--- /dev/null
@@ -0,0 +1,81 @@
+"use strict";
+
+var psnc = psnc || {};
+
+psnc.BetterSession = function (options) {
+    $.extend(this, this.defaults, options);
+
+    // account for network delays and rendering time
+    this.warnAfter -= 5;
+    this.expireAfter -= 5;
+
+    this.postponeWarn = _.debounce(this.warn, this.warnAfter * 1000);
+    this.postponeExpire = _.debounce(this.expire, this.expireAfter * 1000);
+
+    $(this.warnSel).find('button').on('click', $.proxy(this.ping, this));
+
+    // update session whenever user loaded sth with ajax...
+    $(document).ajaxComplete($.proxy(this.update, this, true));
+    // ...or in another window
+    $(window).on('storage', $.proxy(this.update, this));
+
+    this.update(true);
+
+    return this;
+};
+
+psnc.BetterSession.prototype = {
+    defaults: {
+        expired: false,
+        warnAfter: 3300,
+        expireAfter: 3600,
+        key: 'lastActivity',
+        pingUrl: '/session/ping/',
+        warnSel: '#better-sessions-warn',
+        expireSel: '#better-sessions-expire',
+        timerSel: '#better-sessions-timer'
+    },
+
+    update: _.throttle(function (local) {
+        if (this.expired) return;
+
+        $(this.warnSel).hide();
+        clearInterval(this.timer);
+
+        // postpone expire message and warning
+        this.postponeWarn();
+        this.postponeExpire();
+
+        // update timestamp only if it is local event
+        if (local === true)
+            localStorage.setItem(this.key, new Date());
+    }, 1000),
+
+    ping: function () {
+        var self = this;
+        $.post(this.pingUrl, {}, function(response) {
+            // session is implicitly extended after every ajax request
+            if (response.status === 'expired')
+                self.expire();
+        }, 'json');
+    },
+
+    warn: function () {
+        this.timer = setInterval($.proxy(this.updateTimer, this), 1000);
+        this.updateTimer();
+        $(this.warnSel).show();
+    },
+
+    expire: function () {
+        this.expired = true;
+
+        $(this.warnSel).hide();
+        $(this.expireSel).show();
+        clearInterval(this.timer);
+    },
+
+    updateTimer: function() {
+        var remaining = Date.parse(localStorage.getItem(this.key)) - new Date() + (this.expireAfter * 1000);
+        $(this.timerSel).text((humanizeDuration(remaining, {language: 'pl', round: true}) || 'chwilÄ™'))
+    }
+};