Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript bookmarklet/iFrame to auto-refresh loaded page if no activity detected within set timeframe?

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.

like image 756
Sootah Avatar asked Sep 03 '11 22:09

Sootah


2 Answers

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;
    }
}())
like image 165
c69 Avatar answered Sep 19 '22 12:09

c69


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>
like image 34
Abdo Avatar answered Sep 18 '22 12:09

Abdo