prototype.jsクックブック02 Now Loading...の出し方

非同期で処理を行うようになると必然的に必要になってくるのが、いわゆるプログレスバーのように処理中であることを知らせるUIだと思う(まぁ、軽い処理ならばいらないけど)。そこで、その方法を説明する。ここでのやり方はAjax.Requestの部分とは完全に切り離して作れるから結構汎用的に使えると思う。

ただし、一つ弱点があるので、それは最後に書いておく。

サンプル:http://ya-lab.main.jp/prototype-js-cookbook/02_now_loading_on_the_web/demo.html

<html><head>
  <title>prototype.js Cookbook 02: now loading on the web</title>
  <script type="text/javascript" src="prototype.js"></script>
  <script type="text/javascript">
		
    // 何か重い処理を非同期で実行する関数
    function execute_something_heavy() {
      // 実際は重い処理に必要なパラメータを構築しよう。
      var params = '';
			
      // このサンプルでは3秒スリープするCGIに処理を投げる。
      var url = 'heavy_task.cgi'; 
			
      // 下記関数の意味は「urlへparamsを引数にPOSTするという意味。
      new Ajax.Request (
        url,
        {
          method: 'POST',
          parameters: params
        }
       );
			
    }
		
    // 今回の要(かなめ)はここ。
    // この部分により、”すべて”の非同期アクセスのイベント(ここではonCreateとonComplete)を
    // キャッチしてNow Loadingメッセージを制御する。
    Ajax.Responders.register({
      onCreate: function() {
        Element.show($('loading'));
      },
      onComplete: function() {
        Element.hide('loading');
        alert('complete');
      }
    });

    // Now Loading部分を非表示にするため、windowのロード時に隠す。
    // <body onload="">でやっても良いが、個人的には<script>タグ内で
    // やった方があとで読みやすい気がする。
    Event.observe(window, 'load', function() { 
      Element.hide('loading'); 
    }, false);
    </script>
	
    <!-- ちょっとNow Loading...っぽいデザインにしておこう -->
    <style type="text/css">
      .now_loading {
        color: white;
        background-color: red;
        width: 100px;
        font-size: 80%;
        float: right;
        margin-top: 0px;
    }
  </style>
</head>
<body>
<div id="loading" class="now_loading" >Now Loading ...</div>

<a href="#" onclick="execute_something_heavy(); return false;">
  Execute something heavy.
</a>
</body>
</html>

さぁ、弱点とは何か? それはこのAjax.Responders.register(...)部分に原因がある。というのもこの部分によってすべてのAjax通信に対してNow Loadingの表示・非表示を切り替えているから、複数のAjax通信が平行して行き交うと最初の通信が終了した時点でNow Loadingの表示も終了してしまうんだ。

だから実際に使う時には現在の通信数を数えて、その数によって表示・非表示を制御する事になる。といってもAjax.Responders.regiseterの中で数えるだけだから変更範囲は狭いけどね。