5

I have a browser-based application that I use at work (as effectively all corporate apps are now browser-based for obvious reasons) that has an annoyingly short session timeout. I'm not sure precisely what the session timeout is set to, but it's something along the order of 5-10 minutes.

Inevitably whenever I have to use it the session has timed out, I enter the information into the app, submit it, and then the page loads with a brand new session without any of the information actually being passed on - all I get is a new session. I then have to re-enter the information and submit it again in order to have it actually pull up what I want. Of course, I could first refresh the page and then enter the info, but I never know if the session is timed out or not and occasionally it runs painfully slowly so this is a waste of time. Our development team's inability to foresee that little things like this are not only annoying, but also end up costing us a ton of money when you consider the amount of time lost (I work for a VERY large corporation) just waiting for the blasted thing to reload and then having to re-enter the submitted information if a pre-refresh was forgotten as it usually is happens to be beyond me. At some point I'm hoping to become the liaison between the programmers and our customer service body.

Anyway, I digress.

What I'm looking to do is this: I'd like to create a Javascript bookmarklet or something that will automatically refresh whatever page it happens to be on if activity isn't detected within a certain timeframe. This timeframe will be a bit short of whatever I end up figuring out what the session timeout is. Basically I just want to make the page reload itself every, say, five minutes if there hasn't been activity within that period. (I don't want it to refresh out of the blue because the time is up while I'm in the middle of using the app, the only time it should do the auto-refresh is if the app page has been sitting idle)

Can this be done with a Javascript bookmarklet? Should I program a page "wrapper" of sorts that loads the application page within an iFrame or something of the sort? The app site that I use has many subpages, and I'd prefer for it to refresh whatever page I happen to be on at the time if the auto-refresh timeout occurs. Of course, if that isn't possible I'd accept it just reloading the main site page if that's not easily possible since if I've been out of the app long enough for the timeout to happen then I likely don't need to still be on whatever account/page I was on at the time.

Hopefully I've explained myself well enough. The logic is simple - if no activity detected withing x amount of time, refresh the current page is the gist of it.

Thank you, my StackOverflow brethren, yet again for your assistance.

-Sootah


Since I have no ability to influence the coding of the page itself, I've got to have the most simple solution possible. A bookmarklet that times the last refresh/pageload and then refreshes the same page if the timeout is reached would be perfect.

If that's not possible, then if I could write a simple page that I could run from the local computer that'd do the same function by loading the page in a frame or something that'd also be acceptable.


EDIT 10/3/11 7:25am MST

Since I work graves and an odd schedule at work (and this site, unfortunately, being blocked there since it's considered a 'forum' - I work in finance, they're overly cautious about information leakage) before I award the bounty, does one of these event detectors detect the last time the page loaded/? Something like document.onload or whatnot. I'm thinking that setting the timer from the last time the page was loaded is going to be the simplest and most effective approach. My mouse may move over the browser that I have the site open in inadvertently while working on other things, and if the timer resets because of that without me actually having interacted with the site in such a way that a page loads/reloads then the session times out.

Sootah
  • 1,771
  • 3
  • 23
  • 42
  • 1
    You might be able to do better than this and poll with ajax against some basic service. That might keep your session alive, and you wouldn't even need to detect activity or add any logic other than the poll. – Stefan Kendall Sep 03 '11 at 22:58
  • @Stefan. Good idea, no need for any logic besides polling. However, I think it's easier to inject bookmarklet code that places a hidden frame and refreshes it than to have XHttpRequest calls. If you're thinking about using jQuery, from experience, it's very tedious to inject multiple scripts since you need to have jquery's libary loaded first, then make the call to $.ajax. – Abdo Sep 28 '11 at 22:44
  • I start out my greasemonkey scripts by pasting in jquery, as chrome doesn't work the same as firefox for including scripts. If you accept this one limitation, it's not so bad. – Stefan Kendall Sep 28 '11 at 23:29
  • I do that too when I have some dynamic server side scripts I would like to inject. It makes life easier. If you want to do it from the 1-liner bookmark, I guess it gets pretty hard to debug, no? – Abdo Sep 29 '11 at 22:04
  • 2
    Bookmarklet isn't a very good idea. Get some code (e.g. c69's one) and use it as *userscript* - via GreaseMonkey in Firefox or somewhat – kirilloid Sep 30 '11 at 15:28

4 Answers4

4

This is the bookmarklet code #1 for you, set up to FIVE seconds. Change time to what you like more.

javascript:
(function () { 
    var q = null;
    function refresh() { window.location.reload(); }
    function x() { clearTimeout(q); a(); }
    function a() { q = setTimeout( refresh, 5000 ); }

    document.body.onclick = x;
    document.body.onmousemove = x;
    document.body.onmousedown = x;
    document.body.onkeydown = x;
}())

p.s.: would have been nicer to include eventListeners, but i suppose you need to support IE8, too, so i replaced them with inline events, - if you DON'T need IE8, use code #2:

javascript:
(function () { 
    var q = null;
    function refresh() { window.location.reload(); }
    function x() { clearTimeout(q); a(); }
    function a() { q = setTimeout( refresh, 5000 ); }

    document.body.addEventListener( "click", x, false );
    document.body.addEventListener( "mousemove", x, false );
    document.body.addEventListener( "mousedown", x, false );
    document.body.addEventListener( "keydown", x, false );
}())

edit: in response to comments, here is code #3 with pulling, instead of refreshing page. Yet, despite advices to use iframe, i decided it might be desirable to not execute scripts on that page, so we will use img instead:

javascript:
(function () { 
    var q = null;
    var u = window.location.href;
    var i = document.createElement('img');
    i.style = "width: 1px; height: 1px;";
    document.body.appendChild(i);
    function refresh() {
        i.src = "";
        i.src = u;
        x(); 
    }
    function x() { clearTimeout(q); a(); }
    function a() { q = setTimeout( refresh, 5000 ); }

    var evs = ['click', 'mousemove', 'mousedown', 'keydown']; 
    for( var j = 0; j < evs.length; j++) {
        document.body['on'+evs[j]] = x;
    }
}())
c69
  • 19,951
  • 7
  • 52
  • 82
  • yet, it would better to make it a greasemonkey / user script, than a bookmarklet. BUT one can only be run in Firefox, Opera or Chrome. IE needs plugin for that, and i doubt your company policy allows it. – c69 Sep 30 '11 at 15:24
  • Instead of refreshing the page, it would proabably be more valuable to open the current page in an iframe, and then close it. This would allow for the already filled in forms to remained intact. Then it is ultimately up to the OP. – Linsey Sep 30 '11 at 23:35
  • well. it depends, but in generally , wouldn't be to hard to replace `location.reload` with 'document.createElement('iframe')' and setting its _src_ to current page's _location_ value ;) – c69 Oct 01 '11 at 00:48
  • location.reload doesn't work because on reload, your timers and events are lost. iframes is one way or ajax requests to the server solve this problem. – Abdo Oct 02 '11 at 23:20
  • code #3 helped me where there is restriction to use chrome extensions :) – Samtech Jan 06 '21 at 08:26
2

Create a bookmark and place the code below in the "url" value. Please note that you should change the values of "sessiontimeout" and "checkinterval". They're both in milliseconds.

javascript:(function(){var lastmove = new Date().valueOf(),sessiontimeout=10000,checkinterval=1000;document.onmousemove = function(e){lastmove= new Date().valueOf();};timer = setInterval( function() {var differential = (new Date().valueOf() - lastmove);if (differential > sessiontimeout) {var iframe = document.getElementById("bkmrkiframerefresher");if (iframe) { document.getElementsByTagName("body")[0].removeChild(iframe);} iframe = document.createElement("iframe");iframe.setAttribute("src", "/");iframe.setAttribute("width", 0);iframe.setAttribute("height", 0);iframe.setAttribute("style", "width:0;height:0;display:none;");iframe.setAttribute("id", "bkmrkiframerefresher");document.getElementsByTagName("body")[0].appendChild(iframe);lastmove = new Date().valueOf();} }, checkinterval);})();

This is a bookmarklet that will inject the code below in the page. I tested the bookmarklet in Chrome. It worked on multiple sites except stackoverflow, it seems that they block framing for security reasons. Before you leave your desk, open the website which session you wanna keep alive, then click the bookmarklet on it. Once you're back, refresh the page in order to get rid of the running timers.

The formatted (and commented) code is:

<script type="text/javascript">
            // last time the mouse moved
            var lastmove = new Date().valueOf();
            var sessiontimeout=10000;
            var checkinterval=1000;

            // reset the last time the mouse moved
            document.onmousemove = function(e){
                lastmove= new Date().valueOf();
            }

            // check periodically for timeout
            timer = setInterval( function() {

                var differential = (new Date().valueOf() - lastmove);

                if (differential > sessiontimeout) {
                    var iframe = document.getElementById("bkmrkiframerefresher");
                    // iframe already exists, remove it before loading it back
                    if (iframe) {
                        document.getElementsByTagName("body")[0].removeChild(iframe);
                    }

                    // alert("more than 10 secs elapsed " + differential);
                    // create an iframe and set its src to the website's root
                    iframe = document.createElement("iframe");
                    iframe.setAttribute("src", "/");
                    iframe.setAttribute("width", 0);
                    iframe.setAttribute("height", 0);
                    iframe.setAttribute("id", "bkmrkiframerefresher");
                    iframe.setAttribute("style", "width:0;height:0;display:none;");
                    document.getElementsByTagName("body")[0].appendChild(iframe);

                    // reset counter.
                    lastmove = new Date().valueOf();
                }
            }, checkinterval);

        </script>

Stefan suggested above that you need no logic besides polling. The edited code is the following:

<script type="text/javascript">
            var pollInterval=1000;

            timer = setInterval( function() {
                    var iframe = document.getElementById("bkmrkiframerefresher");
                    // iframe already exists, remove it before loading it back
                    if (iframe) {
                        document.getElementsByTagName("body")[0].removeChild(iframe);
                    }

                    // create an iframe and set its src to the website's root
                    iframe = document.createElement("iframe");
                    iframe.setAttribute("src", "/");
                    iframe.setAttribute("width", 0);
                    iframe.setAttribute("height", 0);
                    iframe.setAttribute("id", "bkmrkiframerefresher");
                    iframe.setAttribute("style", "width:0;height:0;display:none;");
                    document.getElementsByTagName("body")[0].appendChild(iframe);
                }
            }, pollInterval);

        </script>
Abdo
  • 13,549
  • 10
  • 79
  • 98
1

This code only reload the page once
Here is a bookmarklet(inspired by Kaj Toet's pseudo code), tested in Chrome and Safari, change the timeout value with the var time at the start of the line
Onliner:

javascript:var time = 500; var timeoutFunc = function(){location.reload(true);};timeout = setTimeout(timeoutFunc,time);document.onmousemove = function() {clearTimeout(timeout);timeout = setTimeout(timeoutFunc,time); };

Code

//The time in milliseconds before reload
var time = 500;
//The function that is called when the timer has reached 0
var timeoutFunc = function()  { 
    location.reload(true);
};
//start the timer
timeout = setTimeout(timeoutFunc,time);
//restart the timer if the mouse is moved
document.onmousemove = function() {
    clearTimeout(timeout);
    timeout = setTimeout(timeoutFunc,time); 
};
MTönnberg
  • 19
  • 3
  • I think this code will execute only once because when the location is reloaded, the "document.onmousemove" will be gone. Please correct me if I'm wrong. The way I attempted to solve this problem in my proposed solution is to have a hidden iframe injected instead and refresh it on a setInterval basis. – Abdo Sep 28 '11 at 09:25
  • instead of refreshing the page maybe its feasible to create an "activity" instead. Sootah, do you know what the server counts as an activity? – MTönnberg Sep 30 '11 at 07:43
  • Ajax calls to server or creating an iframe that has a path on the server. – Abdo Oct 01 '11 at 00:49
0

pseudocode

timeout = settimeout("call",200);
document.onmousemove = function() { timeout = new timeout("call",200); }
function call() {
    document.refresh();
}

like this?

RobotRock
  • 4,211
  • 6
  • 46
  • 86