Ajaxオブジェクト
prototype.js解読のもう一つの山場。というか、ここが肝でしょうか。Ajax.Responders, Ajax.Base, Ajax.Request, Ajax.Updater, Ajax.PeriodicalUpdaterはそれぞれ別に解読します。
Ajaxオブジェクトは上記のAjax関連のクラス・オブジェクトの名前空間(他と名前の衝突を避ける)として使用されます。
基礎知識
ここで、初級者(=筆者^^;)のために、おさらい。
Ajaxとは、「Asynchronous JavaScript + XML」の略。「非同期(Asynchronous)なJavaScriptとXMLを利用した技術」というような意味です。詳しくは>こちら<をご覧ください。
厳密な定義はともかく、一般的には「読み込こんだページはそのままに、更にサーバと通信してデータを取得し、ページの一部を更新する」というのがAjax、という感じになっています。
これを実現するのがJavaScriptのXMLHttpRequestオブジェクトです。ページ上でサーバとの通信を担います。以下の例は意図的にシンプルにした例です。IE6.0のみで動作します。
ただし、読み込むファイル(test.txt)は文字コードUTF-8で記述してください。でないと文字化けします。WinXP付属のメモ帳でも保存時に文字コードの指定ができます。(参考:XMLHttpRequestのresponseTextで扱える文字コードについて - Backstage of theater.js)
【参考】 [test.htm] <html> <head> <title></title> <script language="javascript"> <!-- var req = null; function test(){ req = new ActiveXObject("MSXML2.XMLHTTP"); //XMLHttpRequestオブジェクト作成(IE6のみ) req.onreadystatechange = write; //onreadystatechangeに実行する関数を設定 //関数は通信状況が変化した際に実行される req.open('GET', 'test.txt', true); //URL等を設定 req.send(''); //送信 } function write(){ //通信状況が変化した際に実行される関数 if(req.readyState == 4){ //readyStateプロパティが4(受信完了)であれば処理する document.getElementById('test').innerHTML = req.responseText; //responseTextプロパティを画面に書き込む } } //--> </script> </head> <body> <div id="test"></div> <button onclick="test();">TEST</button> </body> </html> --------------------------------------------------------- [test.txt]このファイルを同一ディレクトリに用意。UTF-8で記述すること。 Ajax(XMLHttpRequest)のテスト
「サーバと通信」と書きましたが、ローカルでも動作します。TESTボタンを押すと、「Ajax(XMLHttpRequest)のテスト」という文字列が表示されます。
非常に簡単に説明すると、
- XMLHttpRequestオブジェクトを作成
- onreadystatechangeプロパティに実行する関数を指定。
- openメソッドでURL等を設定。
- sendメソッドで送信。
- onreadystatechangeプロパティに設定した関数内で、readyStateプロパティが4(受信完了)の場合に、responseTextプロパティ等から受信データを取得。
- あとはお好きにw
という流れになります。
実際はブラウザの違いを吸収する等、他にも処理が必要です。これを実装し、機能追加したのがprototype.jsのAjaxオブジェクト(および配下のクラス・オブジェクト)といえます。上の例をprototype.jsで書き直すとこうなります。
【参考】 <html> <head> <title></title> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script language="javascript"> <!-- function test(){ new Ajax.Updater('test', 'test.txt', {method:'get'}); } //--> </script> </head> <body> <div id="test"></div> <button onclick="test();">TEST</button> </body> </html>
なお、Ajax、XMLHttpRequestについての詳しい(正しい?)説明は他のサイトを参照してください・・・。
解読
【抜粋】 var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0 }
Ajaxオブジェクトを作成しています。ここではメソッドとプロパティが一つずつ定義されていますが、以降で更に追加されます。*1
getTransportメソッド
前述の「基礎知識」で提示した例は、NetscapeやOpreaでは動作しません。これはブラウザによってXMLHttpRequestオブジェクトの取得方法が異なるためです。この差を吸収するためのメソッドがgetTransportです。
Try.theseメソッドによりXMLHttpRequestオブジェクトの取得を試み、取得できたものを返却しています。上から順に、IE6、IE5.5以前、他のブラウザのXMLHttpRequestオブジェクト取得用関数です。取得できなかった場合はfalseを返却します。
activeRequestCountプロパティ
activeRequestCountは現在処理中のリクエストの数を格納しています。
XMLHttpRequestオブジェクトによる通信は、同時に複数行うことが可能です。これが非同期(Asynchronous)といわれる所以です。
以下の例は、Ajax.activeRequestCountが2以上の状態を作りたいがために、サーバサイドでJSPを使いました。
【例】 [test.htm] <html> <head> <title></title> <script language="javascript" src="./prototype.js" charset="utf-8"></script> <script language="javascript"> <!-- function test(){ new Ajax.Request( 'test.jsp', { method: 'get', onComplete:function(req){ $('test').innerHTML += req.responseText + ":" + Ajax.activeRequestCount; } }); } //--> </script> </head> <body> <div id="test"></div> <button onclick="test();test();">TEST</button> </body> </html> --------------------------------------------------------- [test.jsp] <%@ page contentType="text/plain;charset=utf-8" %> <%@ page import="java.util.*, java.io.*" %> <% //キャッシュ無効化 Calendar today = new GregorianCalendar(); response.setDateHeader("Last-Modified", today.getTime().getTime()); response.setDateHeader("Expires", 0); response.setHeader("Pragma","no-cache"); response.setHeader("Cache-Control","no-cache"); //2秒待つ Thread.sleep(2000); %> Ajax(XMLHttpRequest)のテスト
htmのボタンを押すと、以下が表示されます。(タイミングによっては違う場合もあります^^;)
【上記例の実行結果】 Ajax(XMLHttpRequest)のテスト :2 Ajax(XMLHttpRequest)のテスト :1
断りなくAjax.Request、サーバサイドのJSPを例に使ってしまいました。Ajax.Requestの説明は以降で行います。JSPは環境(JAVA、Apache等)がないと動作しません。筆者の経験言語・環境により、現在使えるのがJSPくらいなので、以降サーバサイドの例が必要な場合はJSPを使用します。本当はPHPやRubyがいいのでしょうけど・・・。