View  Edit  Attributes  History  Attach  Print  Search

Part2 - onbeforeunload Event

In this tutorial, we are going to use onbeforeunload event to let the user know the progress of loading next page.

onbeforeunload

onbeforeunload is an event that fires before the unload event when the page is unloaded. It is not a public standard. It is introduced by Internet Explorer 4. However, other browser realized the importance of the event for web application. Most modern browsers now support this event.

Dependencies

The major dependency is ModalBox. You can use other modal popup library if you want. ModalBox is chosen because it is merely a function call to show the modal popup. It depends on prototype.js and scriptaculous. They are included in the ModalBox download package. So, all you need is the following code:

<link rel="stylesheet" href="/css/modalbox.css" type="text/css" media="screen" />
<script type="text/javascript" src="/js/prototype.js"></script>
<script type="text/javascript" src="/js/scriptaculous.js?load=effects"></script>
<script type="text/javascript" src="/js/modalbox.js"></script>

Implementation

The implementation consists of

  1. the script to show the modal popup
  2. the long running process
  3. the progress query page

Script

The script is simple. We only write the function to show the modal popup which will include in an iframe element. Line 1 to 14 can be put in a common source file (e.g. checkprogress.jsp, checkprogress.php) so you can include them and reuse them. Line 13 to 16 will be the configuration of

  1. URL to check the progress
  2. ModalBox options
  3. The event to trigger the popup box (onbeforeunload in this case)
  1. checkprogress=function() {
  2.         window.setTimeout(function(){
  3.                         var console = document.createElement("iframe");
  4.                         console.src = checkprogress.url;
  5.                         console.frameBorder = 0;
  6.                         console.allowTransparency = true;
  7.                         console.style.width = '95%'
  8.                         Modalbox.show(console, checkprogress.options);
  9.                         Modalbox.deactivate();
  10.                 }, 1000);
  11. }
  12. checkprogress.url = '/ajax/progress.php';
  13. checkprogress.options = {title: "Loading...", width: 300};
  14.  
  15. window.onbeforeunload = checkprogress;

Please also note that checkprogress is actually is calling an anonymous function with window.setTimeout(). That means the modal popup will not show if the next page is loaded with one second (line 11).

process.php

This PHP page can be anything. This example only sleep for 20 seconds and redirect to the Referer header. In actual usage will be updating the progress in the loop.

<?

$n=20;
for ($i = 0; $i < $n; $i++) {
        sleep(1);
}

header("Location: ".$_SERVER['HTTP_REFERER']);

?>

progress.php

This PHP will read the progress updated by process.php. This example shows the server time. Since it is hosted in a iframe, the background color is set to bransparent. It also set the meta refresh to update the page automatically.

<html>
  <head>
    <meta http-equiv="refresh" content="1">
  </head>
  <body style="background-color:transparent">
    <? echo date("r"); ?>
  </body>
</html>

Demo

Click here to see the effect.

Note

There was an attempt to implement the same function with AJAX (i.e. client-side refresh) without an iframe (i.e. server-side refresh):

  1. checkprogress=function() {
  2.         window.setTimeout(function(){
  3.                         var console = document.createElement("div");
  4.                         console.id = 'console';
  5.                         console.src = checkprogress.url;
  6.                         console.style.display = "none";
  7.                         document.documentElement.appendChild(console);
  8.                         Modalbox.show(console, checkprogress.options);
  9.                         Modalbox.deactivate();
  10.                         setTimeout(_f, 1);
  11.                 }, 1000);
  12.         var _f = function() {
  13.                 var url = checkprogress.url
  14.  
  15.                 new Ajax.Request(url, {
  16.                   method: 'post',
  17.                   onSuccess: function(transport) {
  18.                         $("console").innerHTML = transport.responseText;
  19.                         setTimeout(_f, 1000);
  20.                   }
  21.  
  22.                 });
  23.         }
  24. }

However, this does not work quite well because of cross-browser issue. Mozilla browsers (e.g. FireFox, SeaMonkey) and Internet Explorer can start an AJAX request when the page is being unload. Google Chrome, however, is still running the script but it does not invoke the AJAX request. So, it does not work with Chrome. I think it is the behavior of WebKit browsers (e.g. Safari). If you only target for FireFox and IE, you can use the code above and a more simple progress.php (i.e. you can remove all the HTML tags).