Ajaxの普及とJavaScriptライブラリの出現や発展は車の両輪のように進んできた。Prototype.jsの出現はその先駆けだったといってよいだろう。今回は、そのAjax関連機能を取り上げる。バージョン1.6.0.2、Windows環境の場合で説明する。

サーバとの送受信

サーバとWebブラウザとの間でデータを送受信する際に、もっとも多く用いられるのはAjax.Requestだ。これはPrototype.jsのClassによって構築されているので、ここではクラスの1つとして紹介する。基本的な構成は以下のとおりだ。最初にnewを記述してインスタンスを生成させるようにすることが必要だ。

new Ajax.Request( 'アクセスするURL', {
  method : 'get'もしくは'post',
  // ..... その他オプション .....
  onSuccess : function( transport )  {
    // ..... サーバから正常にデータを受信したとき .....
    // (ステータスコード2xxのとき)
    // 引数transportはサーバから受信したデータなど、以下同じ
  },
  onFailure : function( transport )  {
    // ..... サーバからデータを受信できなかったとき .....
    // (ステータスコード2xx以外のとき)
  },
  onException : function( transport, ex )  {
    // ..... 送受信時に何らかのエラーが発生したとき .....
  }
} )

サーバにアクセスするときのHTTPメソッドはgetかpostを記述する。そしてリクエスト送信前後に行う処理をコールバック関数で記述する。引数transportは、サーバから受信したデータなどが収められたオブジェクトだ。オプションの詳細はAjax Optionsで参照できる。

受信したXMLデータでWebページを更新

では例として、リスト1のようなXML形式のデータを受信して、リスト2のようにHTMLの<ul><li>に変換してリンクを表示させる方法を紹介したい。

【リスト1】 XML形式のブックマークデータ(独自形式、文字コードUTF-8)

<?xml version="1.0"?>
<bookmark>
  <item>
    <title>いまからはじめるPrototype.js</title>
    <link>http://journal.mycom.co.jp/series/prototypejs/001/menu.html</link>
  </item>
  <item>
    <title>いまからはじめるScript.aculo.us</title>
    <link>http://journal.mycom.co.jp/series/scriptaculous/001/menu.html</link>
  </item>
</bookmark>

【リスト2】 HTMLに変換後のブックマーク(<div id="panel"></div>内に表示)

<ul>
  <li><a href=".....">いまからはじめるPrototype.js</a></li>
  <li><a href=".....">いまからはじめるScript.aculo.us</a></li>
</ul>

図1 リスト2の画面表示

例1 IE7, Opera9.2, Safari3の場合


1.Ajax.Requestのインスタンスを生成する処理を記述する(リスト3)。正常にデータを受信できたときは上記の変換処理を行い、その他の場合は簡単なメッセージを表示させるようにする。

【リスト3】 Ajax.Requestのインスタンスを生成

new Ajax.Request( 'サーバのURL', {
  method : 'get',
  onSuccess : function( transport )  {
    // ..... XMLからHTMLへの変換処理 .....
  },
  onFailure : function( transport )  {
    $( 'panel' ).update( 'データを受信できませんでした' );
  },
  onException : function( transport, ex )  {
    $( 'panel' ).update( 'エラーが発生しました<pre>' + ex.message + '</pre>' );
  }
} );

2.初期設定として、新たに生成した<ul>と、リスト1のルートタグにあたるDOMオブジェクト(documentElement)の参照を変数に代入しておく。

var ul  = new Element( 'ul' );
var doc = transport.responseXML.documentElement;

3.リンク情報を持つ<item>を逐次参照し、HTMLに変換する

$A( doc.getElementsByTagName( 'item' ) ).each( function( tag )  {
  if ( !Prototype.Browser.IE )  tag = Element.cleanWhitespace( tag );
  var children = tag.childNodes;
  // <a>の生成(children[ 0 ] : <title>, children[ 1 ] : <link>)
  var a = new Element( 'a', { href : children[ 1 ].firstChild.nodeValue } )
                .update( children[ 0 ].firstChild.nodeValue );
  // ..... <a>を<li>の子要素とする .....
  var li = a.wrap( 'li' );
  // ..... <ul>に<li>を追加 .....
  Element.insert( ul, li );
} );

4.すべての<item>から<li>を作成したら、<ul>を画面表示の要素として追加する

$( 'panel' ).insert( ul );

例2 Firefox2の場合

Firefoxでは、上記の3.について、セレクタを含むElementのメソッドをより多く実行可能だ。以下にその例を示す。

// CSSセレクタで<item>を逐次参照
Element.select( doc, 'item' ).each( function( tag )  {
  // <title>と<link>のDOMオブジェクトを参照
  var title = Element.firstDescendant( tag );
  var link  = Element.next( title );
  // <a>および<li>を生成
  var li = new Element( 'a', { href : link.firstChild.nodeValue } )
                  .update( title.firstChild.nodeValue )
                  .wrap( 'li' );
  // <li>を<ul>に追加
  ul.insert( li );
} );

例1と例2を合わせると以下のようになる。ここではPrototype.Browser.Geckoを用いてWebブラウザの種類に応じて処理を変えられるようにしている。できればどのWebブラウザでも同じ方法で処理したいのだが、どうしてもできないときは、こうした処理の振り分けが必要になる。

new Ajax.Request( 'サーバのURL', {
  method : 'get',
  onSuccess : function( transport )  {
    var ul  = new Element( 'ul' );
    var doc = transport.responseXML.documentElement;
    if ( !Prototype.Browser.Gecko )  {
      // Firefox以外の処理
    }  else  {
      // Firefoxでの処理
    }
    $( 'panel' ).insert( ul );
  },
  onFailure : function( transport )  {
    $( 'panel' ).update( 'データを受信できませんでした' );
  },
  onException : function( transport, ex )  {
    $( 'panel' ).update( 'エラーが発生しました<pre>' + ex.message + '</pre>' );
  }
} );

その他のAjax関連機能


Ajax.Updater クラス
サーバから受信したHTMLデータでWebページを更新する。JavaScriptを実行するオプションもある。

Ajax.PeriodicalUpdater クラス
定期的にサーバからHTMLデータ受信してWebページを更新する。

Ajax.Responders オブジェクト
どのAjax処理でも共通するコールバック関数を設定しておく。

Webメールクライアントのように多くのユーザーがアクセスするページでもAjaxを導入する例が増えてきた。連載は今回で最後となるが、Prototype.jsをはじめとするJavaScriptライブラリはまだまだ発展を続けている。数年経ってから振り返ったときに、2008年はAjax普及元年と呼ばれるようになっているかもしれない。