|
|
email me
email me
Detecting Page Refreshes :: Using JavaScript on Client-Side
Motivation
I was once asked to add a feature to the highlighting script
so that highlighting would be turned off when a page was refreshed.
I could not think of a simple way to detect when a page was
refreshed, and when I searched on-line I found that not many other
people had come up with good solutions to this problem.
I ended up coming up with my own way to detect refreshes using
cookies and implemented the search highlighting script so that
refreshes would toggle highlighting on and off. See the highlighting script
for more details. Here I give a common method using JavaScript and
hidden form variables which I did not use as well as a unique (as
far as I can tell) method that uses JavScript and cookies that I
did use.
The Common Approach: Hidden Form Variables
In most web browsers, hidden form variables are maintained across
refreshes. That is, even though a page is refreshed, if a hidden
form variable was changed by JavaScript before the refresh, the
changed value will be used after the refresh. Thus, on a page load
JavaScript can check to see if a hidden variable that defaults to
being unset is set. If it is unset, it assumes this is not a refresh
and it sets it. If it is set, it assumes this is a refresh.
An example page that implements this might look like the
following.
<html>
<head>
<script language="JavaScript"> <!--
function checkRefresh()
{
if( document.refreshForm.visited.value == "" )
{
// This is a fresh page load
document.refreshForm.visited.value = "1";
// You may want to add code here special for
// fresh page loads
}
else
{
// This is a page refresh
// Insert code here representing what to do on
// a refresh
}
} -->
</script>
</head>
<body onLoad="JavaScript:checkRefresh();">
<form name="refreshForm">
<input type="hidden" name="visited" value="" />
</form>
</body>
</html>
However, the implementation of this seems to change from web
browser to web browser and even from version to version. In some web
browsers, this works with a refresh but it does not work with a
reset (a "shift-refresh") while in others it works with both. Plus,
the bulk of the coding for this method is buried in the body of the
web page rather than in JavaScript that can be included in a single
line in the header.
The Approach I Use: Session Cookies
I prefer not to use the above method. For one, its behavior is
going to vary from web browser to web browser. Additionally, it
requires a bulk of code in the body of the web page. I would prefer
a method that can be wrapped up almost entirely in a
<script>...</script> so that I
can tuck it away in a .js file and only
have to add a <body> event handler.
So I use JavaScript cookies. On a page unload, the web page sets
a cookie to the name of the web page and another cookie to the
current time in seconds. Then, on page load, the web page retrieves
those cookies and checks the current time. If the name cookie
matches the name of the page and the time cookie differs by the
current time by no more than 5 seconds, then the load is assumed to
be a refresh. Otherwise it is assumed to be a fresh load. In the
case where the page posts data back to itself, it can prevent the
setting of the cookie so that the next load won't look like a
refresh. This method is longer, but I believe it is tighter and more
robust.
An example page that implements this might look like the
following.
<html>
<head>
<script language="JavaScript"> <!--
function checkRefresh()
{
// Get the time now and convert to UTC seconds
var today = new Date();
var now = today.getUTCSeconds();
// Get the cookie
var cookie = document.cookie;
var cookieArray = cookie.split('; ');
// Parse the cookies: get the stored time
for(var loop=0; loop < cookieArray.length; loop++)
{
var nameValue = cookieArray[loop].split('=');
// Get the cookie time stamp
if( nameValue[0].toString() == 'SHTS' )
{
var cookieTime = parseInt( nameValue[1] );
}
// Get the cookie page
else if( nameValue[0].toString() == 'SHTSP' )
{
var cookieName = nameValue[1];
}
}
if( cookieName &&
cookieTime &&
cookieName == escape(location.href) &&
Math.abs(now - cookieTime) < 5 )
{
// Refresh detected
// Insert code here representing what to do on
// a refresh
// If you would like to toggle so this refresh code
// is executed on every OTHER refresh, then
// uncomment the following line
// refresh_prepare = 0;
}
// You may want to add code in an else here special
// for fresh page loads
}
function prepareForRefresh()
{
if( refresh_prepare > 0 )
{
// Turn refresh detection on so that if this
// page gets quickly loaded, we know it's a refresh
var today = new Date();
var now = today.getUTCSeconds();
document.cookie = 'SHTS=' + now + ';';
document.cookie = 'SHTSP=' + escape(location.href) + ';';
}
else
{
// Refresh detection has been disabled
document.cookie = 'SHTS=;';
document.cookie = 'SHTSP=;';
}
}
function disableRefreshDetection()
{
// The next page will look like a refresh but it actually
// won't be, so turn refresh detection off.
refresh_prepare = 0;
// Also return true so this can be placed in onSubmits
// without fear of any problems.
return true;
}
// By default, turn refresh detection on
var refresh_prepare = 1;
-->
</script>
</head>
<body onLoad="JavaScript:checkRefresh();" onUnload="JavaScript:prepareForRefresh();">
<!-- The above is all that is needed. -->
<!-- Below is an example of the use of disableRefreshDetection()
to prevent false refreshes from being detected when forms
are submitted back to this page. If your web page does
not use forms that post back to themselves, then the
below does not matter to you. Omit it. -->
<!-- This is a dummy form. Focus on the onSubmit. -->
<form onSubmit="JavaScript:disableRefreshDetection()">
<input type="submit" />
</form>
</body>
</html>
The above example is long and there are chances that it will
catch some false positives, but in my experience it is more
consistent than other solutions. Additionally, nearly all false
positives can be prevented with the disableRefreshDetection()
function. However, there are still times when a page reset may be
needed and most page resets will look like page refreshes to this
script as well. Note that the first method that uses hidden
variables can still have this same problem depending on the web
browser.
|
|
|