JavaScript フレームワークの比較

JavaScript 開発を大いに強化するフレームワークの概要

最近の Web サイトや Web アプリケーションは、リッチな対話性を実現するためにクライアント・サイドの JavaScript に大幅に依存する傾向があります。この傾向を顕著にしているのは、非同期 HTTP リクエストの出現です。非同期 HTTP リクエストの場合、サーバー・サイドのスクリプトやデータベース・システムからデータやレスポンスを返す際に、ページを最新の状態に更新する必要がありません。この記事では、対話性と応答性に極めて優れた Web サイトおよび Web アプリケーションを素早く簡単に作成できるようにする JavaScript フレームワークの仕組みを探ります。

Joe Lennon, Software developer, Freelance

Photo of Joe LennonJoe Lennon は、アイルランド・コーク出身の 24 歳のソフトウェア開発者です。彼は Apress から出版予定の『Beginning CouchDB』の著者で、IBM developerWorks の技術記事やチュートリアルにも度々貢献しています。余暇は、サッカー、ガジェットの研究、そして Xbox 360 のゲームで楽しんでいます。


developerWorks 貢献著者レベル

2010年 2月 02日

はじめに

JavaScript は、これまで長い間 Web ブラウザー・アプリケーションではクライアント・サイドのスクリプト・インターフェースとして好んで使われてきたオブジェクト指向のスクリプト言語です。JavaScript を使用すると、開発者は Web ページ上のオブジェクトをプログラムで操作できるため、JavaScript はこれらのオブジェクトをオンザフライで操作するためのプラットフォームとなります。JavaScript が初めて紹介された頃は、ありきたりな機能を Web ページに提供するために使用するのが一般的でした。例えばクロックや、ブラウザーのステータス・バーでテキストをスクロールするなどといった機能です。また、ユーザーがリンクにマウスを重ねると、リンクの画像やテキストの色が変わるという「ロールオーバー・リンク」という一般的な機能にも使われてきました。しかし最近の JavaScript は、当時より遥かに貴重な存在になるまでに進化しています。それは、Web ベースのプログラミングにまったく新しいレベルの対話性をもたらす Ajax (Asynchronous JavaScript and XML) の概念が加わったからです。Ajax が登場する以前は、サーバー・サイドを処理したり、データベースにアクセスしたりするには、いずれもブラウザーがページ全体を最新の状態に更新するか、新しいページをレンダリングしなければなりませんでした。これには時間がかかり、ユーザーを苛立たせる原因となるだけでなく、帯域幅とリソースを無駄にすることにもなります。

Ajax は Asynchronous JavaScript and XML の略ですが、XML という語はもはや意味を成していません。Ajax リクエストに対するレスポンスは、XML 以外の形式 (JSON (JavaScript Object Notation) など) で返すこともできるからです。Ajax は、JavaScript を使って Web サーバーに対する HTTP リクエストを非同期に送信させることによって機能します。その目的は、サーバーからのレスポンスをレンダリングする際に、ページ全体を最新の状態に更新したり、新たにページをレンダリングしたりする必要をなくすためです。代わりに開発者は通常、HTTP レスポンスによって返された変更あるいはデータをページに反映するために、DOM (Document Object Model) 操作によって Web ページを部分的に変更します。


JavaScript フレームワークとは何か

JavaScript はそのままでも非常に強力な言語なので、フレームワークを追加しなくても JavaScript で動作するリッチ・インターネット・アプリケーション (RIA) を作成することができます。しかし JavaScript を使いこなすのは簡単なことではありません。その原因は第一に、複数の Web ブラウザーをサポートしようとするときに持ち上がってくる複雑さです。HTML や CSS と同じく、JavaScript の実装もブラウザーごとに異なります。そのため作成する JavaScript コードをどのブラウザーにも確実に対応させるとなると、まるで悪夢のような作業となります。

JavaScript フレームワーク (またはライブラリー) とは、クロスブラウザー対応の JavaScript コードを遥かに簡単に作成できるようにする一連のユーティリティーと関数の集まりです。それぞれのライブラリーは、よく使われているさまざまな Web ブラウザーの最新バージョンで精力的にテストが行われます。したがって、これらのフレームワークのいずれかを使用すれば、JavaScript ベースの RIA が各種ブラウザーおよびプラットフォームで同じように機能することに確信を持てます。

クロスブラウザーの問題に対処するだけでなく、JavaScript フレームワークを使用すれば、DOM 要素を取得、トラバース、操作するコードを簡単に作成することができます。JavaScript フレームワークでは、簡略化した関数で DOM 要素の参照を取得できるだけではありません。DOM トラバース関数を連鎖的に呼び出して、任意のレベルの親要素、子要素、または兄弟要素を検出することもできます。さらに、JavaScript フレームワークはこれらの要素を簡単に操作できる一連の関数を提供します。これらの関数を使って、要素の中身を変更、追加、削除することも、クラスの CSS スタイル設定を操作して要素の外観に影響を与えることも可能です。

JavaScript フレームワークが持つもう 1 つの重要な機能は、イベント処理に対するサポートを改善することです。特定のブラウザーに依存しないイベント処理は、ブラウザーごとに実装が異なることから悪夢となりがちです。そこで、JavaScript フレームワークは一般にブラウザーのイベントをラップし、これらのイベントを処理するのに役立つ一連のクロスブラウザー対応の関数を提供します。一部のフレームワークには、キーボード・ベースのイベント (Escape キー、Return キー、カーソル・キーなどの押下) を表す、一連の標準化したキー・コードも用意されているほどです。

以上の機能はいずれも非常に有益なものですが、JavaScript フレームワークの最近の人気に寄与している側面は別にあります。それは、Ajax サポートです。JavaScript が持つ他の多くの側面と同じく、Web ブラウザーが Ajax をサポートする方法はそれぞれに異なる傾向があることから、すべての Web ブラウザーでサポートされる方法で Ajax を処理するのは骨の折れる仕事です。JavaScript フレームワークには必ずと言ってよいほど、Ajax ライブラリーのサポートが何らかの形で組み込まれています。通常はこれらのライブラリーが、Ajax によるリクエスト・オブジェクトおよびレスポンス・オブジェクトと併せ、レスポンスの評価、DOM 要素の更新、そして特定リクエストのポーリングを行うためのヘルパー関数を提供します。


JavaScript フレームワークの典型的な機能

ここからは、大部分の JavaScript フレームワークに共通する便利な機能をいくつか見ていきます。具体的には、以下の機能を取り上げます。

  • セレクター
  • DOM トラバース
  • DOM 操作
  • ユーティリティー関数
  • イベント処理
  • Ajax

上記の機能それぞれについて、実際の JavaScript フレームワークでの例に沿って説明します。これらの例は、Prototype、jQuery、YUI、ExtJS、MooTools のいずれか、あるいは複数から引用したものです。フレームワークによって実装および構文は異なりますが、一般的に言って、概念には違いはありません。フレームワークごとに詳細な API リファレンス・マニュアルが用意されているので、特定のライブラリーの機能をどのように使用するかを判断する際には、該当するマニュアルを参照してください。


セレクター

現在使用可能な JavaScript フレームワークのほとんどは、要素を素早く選択するためのサポートを何らかの形で実装しています。一般的に言うと、これらのセレクターは HTML 要素の参照を取得するプロセスを大幅に高速化し、ID、クラス名、要素タイプを基準として要素を検索できるようにしています。また、一連の擬似セレクターを使用して要素を検索することも可能です。

例えば、通常の JavaScript を使用して DOM 要素をその ID を基準に選択する場合には、以下のコードを使用します。

var theElement = document.getElementById('the_element');

一方、MooTools では他のいくつかのフレームワークと同じく、簡略化したメソッドでこのアクションを実行することができます。MooTools は要素を選択するだけでなく、一連の MooTools ユーティリティー関数によって要素を拡張します。そのための構文は以下のとおりです。

var theElement = $('the_element');

上記のドル ($) 関数は、すべての JavaScript フレームワークで使用できるわけではありませんが、よく使われている JavaScript フレームワークのいくつかで使用することができます。使用する構文も通常は同様です。Prototype ライブラリーはさらに一歩踏み込んで、ID を基準に一度に複数の要素を選択し、要素の配列を返せるようにしています。MooTools と同じく、これらの要素は Prototype ユーティリティー関数によって拡張されます。Prototype で一度に複数の要素を選択する場合の構文は以下のとおりです。

var elementArray = $('element_one', 'element_two', 'element_three');

コレクションを簡単に繰り返し処理できるように JavaScript フレームワークが提供している関数については、「ユーティリティー関数」のセクションで説明します。

上記に記載した例では、いずれも選択対象とする要素の ID を指定することになっていますが、複数の要素を選択したい場合にはどうすればよいでしょうか。例えば、画像をすべて選択したり、表内で特定の CSS クラス名を持つすべての行を選択したりするような場合です。MooTools (および他のいくつかのライブラリー) には、このような場合に使用できる非常に単純なメソッドがあります。それが、二重のドル ($$) 関数です。この関数はドル関数と同じように機能しますが、ドル関数と異なる点は、引数に要素の ID ではなく、CSS 要素名、クラス名、擬似セレクターを使用できることです。例えば、MooTools を使用して Web ページ上のすべての画像を選択するには、以下のコードを使用します。

var allImages = $$('img');

このコードによって、文書内にあるすべての画像の配列が返されます。この配列に含まれる各画像は、ドル関数によって MooTools ユーティリティー関数を組み込むように拡張されています。

タグ名で要素を選択できるのは便利なことですが、CSS クラスに基づいて要素のサブセットだけを選択したいという場合もあります。そのような場合も、とても簡単に対処することができます。以下の例で MooTools が選択するのは、表内の行のうち、CSS クラスが「odd」のクラスだけです。この方法は、行のストライピング (表の背景色を行ごとに交互に変更すること) を実装する場合に役立ちます。

var allOddRows = $$('tr.odd');

実は、MooTools には行のストライピングを実行するのに、さらに適した方法があります。前の例では表内の奇数の行に「odd」という CSS クラス名が設定されているという前提でしたが、以下のコードの場合、表の行に CSS クラス名を定義する必要はありません。

var allOddRows = $$('tbody:odd');

上記は、指定された基準を満たすすべてのオブジェクトを返す擬似セレクターの一例です。この例では、ページ上の tbody (table body) 要素の奇数の子要素が指定されています。MooTools の擬似セレクターの例には、以下に挙げるものもあります。

  • checked — チェックされたすべての要素 (チェック・マークが付けられたチェック・ボックスなど) を選択
  • enabled — 有効に設定されたすべての要素を選択
  • contains — セレクターに引数として渡されたテキストが含まれるすべての要素 (contains('this text') など) を選択

前述のとおり、すべての JavaScript フレームワークがドル関数を使用して DOM 要素を選択するわけではありません。YUI (Yahoo! User Interface) ライブラリーのバージョン 3 では、ID を基準に要素を選択する場合には以下のコードを使用します (YUI 3 では、ID 自体の前に ID セレクター文字 # を渡さなければならないことに注意してください)。

var theElement = Y.one('#the_element');

同様に、タグやクラス名で要素を取得する場合、YUI では二重のドル関数を使用する代わりに、Y.all 関数を使用します。

var allOddRows = Y.all('tr.odd');

ExtJS も YUI と同じように機能し、ID を基準に要素を選択するには以下の構文を使用します。

var theElement = Ext.get('the_element');

タグおよびクラス名を基準に選択するとしたら、以下の構文を使用します。

var allOddRows = Ext.select('tr.odd');

次のセクションでは、JavaScript フレームワークが DOM のトラバース、つまり選択された要素と親、子、または兄弟の関係を持つ要素を簡単に検索できるようにしている仕組みを説明します。さらに、ライブラリーを使用して DOM を操作することによって要素を変更する方法についても説明します。


DOM トラバース

要素を検索するには、ID、要素タイプ、または CSS クラス名を基準にすることができます。それはそれで便利ですが、要素を DOM ツリー内での位置に基づいて検索したいという場合もあります。別の言い方をすると、例えば特定の要素があり、その要素の親要素、子要素のうちの 1 つ、あるいはその要素の前または次の兄弟要素を見つけたいという場合です。その方法を説明するための例として、リスト 1 に記載する HTML スニペットを使用します。

リスト 1. HTML スニペット (HTML 表)
<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Email Address</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        <tr id="row-001">
            <td>Joe Lennon</td>
            <td>joe@joelennon.ie</td>
            <td><a href="#">Edit</a>&nbsp;
                <a href="#">Delete</a></td>
        </tr>
        <tr id="row-002">
            <td>Jill Mac Sweeney</td>
            <td>jill@example.com</td>
            <td><a href="#">Edit</a>&nbsp;
                <a href="#">Delete</a></td>
        </tr>
    </tbody>
</table>

リスト 1 ではインデントによって、各要素が DOM ノード・ツリーのどの位置に現れるかを示しています。この例では table 要素がルート要素です。このルート要素には theadtbody という 2 つの子ノードがあります。thead 要素の唯一の子要素は、tr です。この子要素にはさらに 3 の子要素 (すべて th 要素) があります。一方、tbody 要素の子要素は 2 つで、どちらも tr です。それぞれの tr ごとに 3 つの子要素があり、これらの行の 3 番目の子にはいずれも 2 つの子が含まれ、その両方が a (アンカー) タグとなっています。

ご存知のとおり、JavaScript フレームワークの Selector 関数を使えば、要素をその ID によって簡単に選択することができます。この例で ID を持つ要素は 2 つです。どちらも tr (表の行) 要素で、ID はそれぞれ row-001、row-002 となっています。この場合、Prototype を使って最初の tr 要素を選択するには、以下のコードを使用します。

var theRow = $('row-001');

前のセクションでは、セレクターを使用して要素タイプまたは CSS クラスを基準に要素を選択することもできると説明しました。この例ですべての td 要素を選択するとしたら、以下の構文を使用します。

var allCells = $$('td');

上記のコードの問題は、これによって DOM 内にあるすべての td 要素が返されることです。つまり ID が row-001 の行にある td 要素だけを取得したいとしたら、このコードは使えないのです。そこで活躍するのが、DOM トラバース関数です。まずは Prototype を使用して、ID が row-001 の tr 要素が持つすべての子を選択してみましょう。

var firstRowCells = theRow.childElements();

上記のコードによって、theRow 変数の子要素の配列が返されます (前のコードで、この変数は ID が row-001 の要素に設定済みです)。

次に、行の最初の子要素だけを取得する場合を考えてみてください。この例で、その子要素に該当するのは「Joe Lennon」という内容の td 要素です。この要素を取得するには、以下の文を使用します。

var firstRowFirstCell = theRow.down();

この通り、簡単なことです。上記のコードは、以下のコードと等価です。

var firstRowFirstCell = theRow.childElements()[0];

また、以下のように表現することもできます。

var firstRowFirstCell = theRow.down(0);

JavaScript が付けるインデックスはゼロ (0) から始まるので、上記の文は基本的に、JavaScript に最初の子を選択するように指示していることになります。したがって、以下のコードを使用すれば、2 番目の子 (joe@joelennon.ie という E メール・アドレスが含まれるセル) を選択することができます。

var firstRowSecondCell = theRow.down(1);

別の方法として、兄弟間で DOM をナビゲートすることも可能です。この場合、2 番目のセルは最初のセルにとって次の兄弟となるので、以下の文を使用することができます。

var firstRowSecondCell = firstRowFirstCell.next();

上記のコードは down() 関数と同じように機能するため、3 番目のセルを選択するとしたら、以下のコードを使用します。

var firstRowThirdCell = firstRowFirstCell.next(1);

Prototype で特定のノードを検索するには、上記のようにインデックスを使用できるだけでなく、CSS セクレターの構文を使用することもできます。リスト 1 を例に、Jill Mac Sweeney の詳細が含まれる行の 2 番目のリンク (「Delete」リンク) を検索してみましょう。

var secondRowSecondLink = $('row-002').down('a', 1);

上記のコードは、ドル関数を使用して ID が row-002 の要素を検索し、それから次の階層にある 2 番目の a (anchor) 要素まで DOM をトラバースします。

フレームワークによっては、「連鎖」トラバース関数を使用することもできます。つまり、トラバース・コマンド同士を連鎖させられるということです。Prototype での上記の例は、以下のようにも表現することができます。

var secondRowSecondLink = $('row-002').down('a').next();

以下の例を見てください。

var domTraversal = $('row-001').down().up().next().previous();

このように、複数の DOM トラバース文を連鎖させて 1 つにまとめて表すことができます。実のところ、上記の例は最終的に ID が row-001tr 要素を選択するため、この連鎖は結局、このセクションで初めに記載したコードと同じ結果が得られることになります!


DOM 操作

これまでのセクションでは、JavaScript フレームワークでは、セレクターと DOM トラバースによって特定要素を容易に選択できることを説明してきました。しかし、Web ページ上の特定要素の外観や内容を変更する場合には、DOM を操作し、その変更内容を適用しなければなりません。JavaScript だけで DOM を操作するのはかなり面倒な作業となりますが、ありがたいことに、ほとんどの JavaScript フレームワークには DOM を簡単に操作するための便利な関数が用意されています。

例えば、the-box という ID が設定された div 要素があるとします。

<div id="the-box">Message goes here</div>

jQuery を使用すれば、以下のコードを使うだけで「Message goes here」というテキストを簡単に変更することができます。

$('#the-box').html('This is the new message!');

実際、この関数のなかに HTML コードを含めると、そのコードはブラウザーによって構文解析されることになります。以下はその一例です。

$('#the-box').html('This is the <strong>new</strong> message!');

上記の div 要素の内容は、DOM では以下のように表現されます。

<div id="the-box">This is the <strong>new</strong> message!</div>

当然、「大なり」記号や「小なり」記号などの特殊文字を実際に使用しなければならない場合もありますが、その場合には特殊な HTML エンティティー・コードを指定する代わりに、jQuery の text 関数を使用することができます。

$('#the-box').text('300 > 200');

このコードによって、div 要素は以下のコードに更新されます。

<div id="the-box">300 > 200</div>

これまでの例では既存のコンテンツが新しいコンテンツで置き換えられていましたが、指定した要素の末尾にコンテンツを追加したい場合にはどうすればよいでしょうか。幸い jQuery には、まさにこの目的のために使用できる append 関数があります。

$('#the-box').append(', here goes message');

上記のコードを元の div 要素に適用すると、div 要素のコンテンツは以下のようになります。

<div id="the-box">Message goes here, here goes message</div>

div 要素の末尾に追加するだけでなく、先頭に追加することもできます。prepend 関数を使えば既存のコンテンツの末尾にではなく先頭に新しいコンテンツが挿入されます。さらに、jQuery には指定した要素の外側 (前後どちらでも) にコンテンツを挿入する関数がある他、コンテンツを置き換える関数、コンテンツを空にする関数、DOM からまとめて要素を削除する関数、要素を複製する関数など、さまざまな関数が用意されています。

通常、JavaScript フレームワークには、DOM を操作するための関数に加え、要素のスタイルおよび CSS クラスをプログラムによって操作するための関数も含まれています。例えば、表の行にマウスを重ねるとその行が強調表示されるようにするため、hover という名前の特殊な CSS クラスを作成し、このクラスを動的に行に追加するとします。YUI では以下のコードを使用することで、行に hover クラスがすでにあるかどうかをチェックし、ある場合にはクラスを削除し、ない場合にはクラスを追加することができます。

if(row.hasClass('hover')) row.removeClass('hover'); else row.addClass('hover');

DOM の場合と同様、ほとんどのフレームワークには CSS を操作するための関数があります。


ユーティリティー関数

多くの JavaScript フレームワークには、JavaScript を使用したアプリケーションの開発を容易にするユーティリティー関数が大量に用意されています。この記事ではすべてを取り上げられないほどのユーティリティー関数があるので、大部分のフレームワークに共通し、とりわけ注目に値するユーティリティー関数の 1 つを取り上げたいと思います。

JavaScript で配列を操作したことがあれば、for ループを使って配列を繰り返し処理し、配列の値を操作するという方法はお馴染みのことでしょう。例えば、リスト 2 のコードを見てください。

リスト 2. 従来の方法による JavaScript 配列のループ処理
var fruit = ['apple', 'banana', 'orange'];
for(var i = 0; i < fruit.length; i++) {
    alert(fruit[i]);
}

リスト 2 のコードに問題はないものの、多少面倒な感があります。そこで、大抵の JavaScript フレームワークには、配列の各要素に対して指定の関数を呼び出す each 関数が組み込まれています。MooTools を使用する場合、リスト 2 のアクションは、リスト 3 のコードを使って実行することができます。

リスト 3. MooTools の each 関数を使用した場合
['apple', 'banana', 'orange'].each(function(item) {
    alert(item);
});

リスト 3 の構文は、YUI や ExtJS での同等の構文とは多少の違いはあるものの、Prototype と jQuery で使用されている構文とまったく同じです。ただし、配列ではなく、ハッシュ・マップまたはオブジェクトに適用する場合の構文は、フレークワークによって異なります。例えば MooTools では、リスト 4 のようなコードを使用します。

リスト 4. MooTools でキーと値のペアで構成されるオブジェクトに each 関数を使用する場合
var hash = new Hash({name: "Joe Lennon", email: "joe@joelennon.ie"});
hash.each(function(value, key) {
    alert(key + ": " + value);
});

一方、Prototype ではリスト 5 のようなコードになります。

リスト 5. Prototype でキーと値のペアで構成されるオブジェクトに each 関数を使用する場合
var hash = $H({name: "Joe Lennon", email: "joe@joelennon.ie"});
hash.each(function(pair) {
    alert(pair.key + ": " + pair.value);
});

それぞれのフレームワークにはこの他にも多数、有用な関数が含まれています。これらの関数は通常、String 関数、Number 関数、Array 関数、Hash 関数、Date 関数などに分類することができます。詳細については、該当する JavaScript フレームワークの API リファレンスを参照してください。


イベント処理

JavaScript フレームワークが実装するクロスブラウザーのイベント処理サポートは、インラインでイベントを追加するという昔ながらの方法から、簡素化された方法への移行を促進します。リスト 6 に記載する jQuery の例では、hover イベントが発生するのに伴って div 要素を強調表示します。

リスト 6. jQuery を使用した hover イベントの追加
$('#the-box').hover(function() {
   $(this).addClass('highlight');
}, function() {
   $(this).removeClass('highlight');
});

これは jQuery が実装する特殊なイベントです。このイベントは 2 つの関数を指定していることがわかりますが、最初の関数は onMouseOver イベントがトリガーされると呼び出され、2 番目の関数は onMouseOut イベントがトリガーされると呼び出されます。このように 2 つの関数が指定される理由は、hover に対する標準 DOM イベントがないためです。今度はこれよりも典型的なイベントとして、click イベントの例を見てください (リスト 7 を参照)。

リスト 7. jQuery を使用した click イベントの追加
$('#the-button').click(function() {
   alert('You pushed the button!');
});

この例を見るとわかるように、このイベントには function 引数が 1 つしかありません。jQuery では、大部分の JavaScript イベントがこのように処理されます。jQuery のイベント・ハンドラーでは、イベントを起動した要素を参照する際にコンテキスト変数が使われるからです。一方、これとは動作が異なるフレームワークもあります。例えばリスト 8 は、リスト 7 のコードに相当する Prototype のコードです。

リスト 8. Prototype を使用した click イベントの追加
$('the-button').observe('click', function(e) {
    alert('You pushed the button!');
});

上記のコードでまず気付く点は、click 関数がない代わりに、observe 関数が使用されていることです。observe 関数は、function 引数自体を参照する前に、1 番目の引数として click イベントを取ります。また、function 関数は引数として e を取っていることにも注目してください。この e が、イベントを起動した要素を参照するコンテキスト変数です。このコンテキスト変数がどのように機能するかを確かめるため、リスト 6 のコードを Prototype のコードに書き直してみます (リスト 9 を参照)。

リスト 9. Prototype を使用した hover イベントの接続
$('the-box').observe('mouseover', function(e) {
    var el = Event.element(e);
    el.addClassName('highlight');
});
$('the-box').observe('mouseout', function(e) {
    var el = Event.element(e);
    el.removeClassName('highlight');
});

jQuery では単純にドル関数を使ってコンテキスト変数を取得しますが、それとは異なり、Prototype では Event.element() 関数を使用しなければなりません。また、mouseover イベント用の関数と mouseout イベント用の関数を分ける必要もあります。

この記事を読み進めているなかで、関数はインラインで作成され、名前が付けられていないことに気付いたことでしょう。これはつまり、関数を再利用できないことを意味します。代わりに名前付き関数を使用する方法は、上記に記載した Prototype での hover の例を使って説明することができます。リスト 10 は、その一例です。

リスト 10. Prototype での改善された hover の例
function toggleClass(e) {
    var el = Event.element(e);
    if(el.hasClassName('highlight')) 
        row.removeClassName('highlight');
    else 
        row.addClassName('highlight');
}

$('the-box').observe('mouseover', toggleClass);
$('the-box').observe('mouseout', toggleClass);

今度は、mouseover イベントと mouseout イベントの両方によって呼び出される関数を 1 つ定義しているだけです。この関数が呼び出されると、要素に highlight という名前のクラスがあるかどうかを調べ、その結果に応じて highlight クラスを削除したり、追加したりします。上記からわかるように、引数 e は暗黙的に渡されます。つまり、observe 関数では明示的にイベントを引数として渡すことはしません。


Ajax

JavaScript フレームワークを使用する理由のなかで最も説得力のある理由は、標準化されたクロスブラウザーの Ajax リクエストが用意されていることです。Ajax リクエストは一般にサーバー・サイドのスクリプトに対して行われる非同期 HTTP リクエストで、このリクエストに対するレスポンスは、XML、JSON、HTML、またはプレーン・テキストの形式で返されます。ほとんどのJavaScript フレームワークで提供される Ajax オブジェクトには、一連のオプションを引数として指定できるリクエスト・メソッドが用意されています。このリクエスト・メソッドのオプションには通常、スクリプトが Web サーバーからレスポンスを受け取ると同時に呼び出されるコールバック関数が含まれます。以下に、ExtJS、MooTools、Prototype それぞれでの Ajax リクエストを順に記載します。

まず初めに記載するのは、ExtJS の典型的な Ajax リクエストです (リスト 11 を参照)

リスト 11. ExtJS の Ajax リクエスト
Ext.Ajax.request({
    url: 'server_script.php',
    params: {
        name1: 'value1',
        name2: 'value2'
    },
    method: 'POST',
    success: function(transport) {
        alert(transport.responseText);
    }
});

ExtJS の request メソッドが取る引数は 1 つだけです。このオブジェクトには、urlparamsmethodsuccess などのさまざまなフィールドがあります。url フィールドには、Ajax リクエストによって呼び出されるサーバー・サイドのスクリプトの URL が含まれます。params フィールドはそれ自体がキーと値のペアからなる 1 つのオブジェクトで、サーバー・サイドのスクリプトにはこのオブジェクトが渡されます。method フィールドの値には、GET または POST のどちらかを設定できます。デフォルトでは未定義として設定されますが、リクエストに params が含まれる場合にはデフォルトで POST として扱われます。最後のフィールド success は、Web サーバーが正常なレスポンスを返した場合に呼び出される関数です。上記の例では、サーバー・サイドのスクリプトがプレーン・テキストを返すことになっています。このテキストは、アラート・ボックスによってユーザーに表示されます。

次に、上記と同じリクエストが MooTools ではどのように表現されるかを調べてみます (リスト 12 を参照)。

リスト 12. MooTools の Ajax リクエスト
new Request({
    url: 'server-script.php',
    data: {
        name1: 'value1',
        name2: 'value2'
    },
    method: 'post',
    onComplete: function(response) {
        alert(response);
    }
}).send();

ご覧のように、MooTools は ExtJS と非常によく似ています。ただし、params ではなく data フィールドを使って変数が渡されること、そしてメソッドを小文字で指定しなければならないという点が異なります。また、MooTools は success ではなく、onComplete でコールバック関数を指定します。そして最後にもう 1 つ ExtJS と異なる点は、MooTools では、Request オブジェクトの send() 関数を使用して実際にリクエストが送信されることです。

最後に、Prototype が上記の 2 つのフレームワークと大々的に異なるかどうかを見てみましょう (リスト 13 を参照)。

リスト 13. Prototype の Ajax リクエスト
new Ajax.Request('server-script.php', {
    params: {
        name1: 'value1',
        name2: 'value2'
    },
    method: 'post',
    onSuccess: function(transport) {
        alert(transport.responseText);
    }
});

やはり、Prototype も同じように機能するものの、構文には多少の違いがあります。第一に、Prototype の Request オブジェクトはコンストラクターの引数として 2 つのパラメーターを取ります。最初のパラメーターは、リクエストの対象 URL で、2 番目のパラメーターは前の 2 つの例でも目にした典型的な Ajax オプションが設定されたオブジェクトです。URL は別個のパラメーターとして渡されるため、当然、オプションのリストには URL は含まれません。さらに注目に値する点は、MooTools とは異なり、Prototype の Ajax Request オブジェクトのコンストラクターは暗黙的にリクエストを送信するため、実際に HTTP リクエストを開始するためのメソッドを呼び出す必要がないことです。

ほとんどの JavaScript フレームワークでは、ここで説明した以上の Ajax 機能をサポートしています。なかでも注目に値する拡張機能の例として、特殊な onSuccess 関数を使用することなく、受け取ったレスポンスを使用して自動的に要素を更新するという機能があります。一部のライブラリーには、事前にビルドされた自動補完機能さえ組み込まれています。これは Google 検索エンジンで見られるような機能で、入力と同時に典型的な検索クエリー候補を表示します。

次のセクションでは、JavaScript フレームワークが Web 開発者に提供する UX (User Experience: ユーザー・エクスペリエンス) 拡張機能について説明します。


UX 拡張機能

この記事ではこれまで、JavaScript フレームワークを使用することでプログラム的な要素にもたらされる利点、そしてこれらの利点によって、インタラクティブなアプリケーションのコードを簡単に作成できるという点のみに焦点を合わせて話を進めてきました。しかし大部分のフレームワークには、それを使用することを魅力的にする別の側面があります。それは、通常は作成するのにかなりの作業が必要となる UI (User Interface) コンポーネントと UX (User Experience) 拡張機能を簡単に統合できることです。

このセクションでは、Prototype、jQuery、YUI、ExtJS、MooTools のそれぞれが提供する UX 拡張機能を個別に検討します。

Prototype

Prototype は、そのまま使用できる UI コンポーネントも、UX 拡張機能も含まれていない数少ない JavaScript フレームワークの 1 つです。Prototype は UI コンポーネントと UX 拡張機能のすべてを、その姉妹ライブラリーである script.aculo.us (最新バージョンは Scripty2 という名前で知られています) に一任しています。script.aculo.us は多岐にわたるエフェクトや振る舞いを Prototype がサポートできるようにします。このライブラリーによって追加されるエフェクトには、例えばハイライト、モーフィング、折りたたみ、振動、スライド、消失などがあります。また、script.aculo.us にはドラッグ・アンド・ドロップのサポートやスライダー、インプレース Ajax エディター、自動補完機能なども用意されています。一部のフレームワークとは異なり、script.aculo.us はコントロール (スライダーや自動補完機能など) の設計を開発者に任せているため、素材となる標準スキンは提供していません。

jQuery

Prototype とは異なり、jQuery はコア・ライブラリーに基本的な UX 拡張機能を組み込んでいます。これらの UX 拡張機能は、script.aculo.us に付属のスライドやフェードなどの基本的なエフェクトと同様のものです。一方、それよりも高度な UX 機能が必要な場合には、jQuery UI ライブラリーをダウンロードする必要があります。このライブラリーには jQuery コア・ライブラリーより多くのエフェクトが含まれているだけでなく、ドラッグ・アンド・ドロップ、サイズ変更、ソートなどの、ユーザーとの対話機能もあります。script.aculo.us と異なる点は、jQuery UI には魅力的なインターフェースの開発を極めて簡単にするウィジェット (コンポーネント) も組み込まれていることです。現時点で組み込まれているコンポーネントには Accordion、Datepicker、Dialog、Progressbar、Slider、および Tabs があります。これらのウィジェットはいずれもテーマの設定が可能であり、これらのウィジェットを独自の Web サイトや Web アプリケーションに適合させるために使用できる広範なテーマも jQuery UI には用意されています。図 1 は、Cupertino テーマを指定した jQuery UI の Datepicker ウィジェットの例です。

図 1. jQuery UI の Datepicker ウィジェット
Datepicker のデモが表示された画面。「Datepicker」というタイトルの下にカレンダーが表示されています。

YUI

Prototype と jQuery にはそのまますぐに使用できる UI ウィジェットがありませんが、YUI (Yahoo! User Interface) ライブラリーには盛りだくさんのウィジェットが組み込まれています。ドラッグ・アンド・ドロップのサポートやサイズ変更の他、YUI のバージョン 2 には自動補完機能、カレンダー・コントロール、カルーセル・コンポーネント、グラフ、ダイアログ、プログレス・バー、リッチ・テキスト・エディター (または WYSIWYG テキスト領域)、スライダー、タブ、ツリーなども用意されています。ただしこの記事を書いている時点での YUI バージョン 3 には、これらのウィジェットはまだ組み込まれていません。図 2 は、複数のコンポーネントを併せて使用した例です。

図 2. YUI の複合サンプル・アプリケーション
E メール・プログラムが表示された画面。画像の URL やサイズなど、画像のオプションを入力できるウィンドウが開いています。

ExtJS

YUI と同じく、ExtJS にもすぐに使用できる数多くのコンポーネントが組み込まれています。なかでも注目に値するのは、インライン編集、ページネーション、フィルタリング、グルーピング、要約、バッファリング、データ・バインディングのサポートを備えた非常に強力なグリッド・コントロールです。ExtJS のコンポーネントはいずれも本格的なルック・アンド・フィールを持つだけでなく、テーマの設定もすることができます。ExtJS に付属のウィジェットにはその他、タブ、グラフ、ウィンドウ (ダイアログ)、ツリー、レイアウト・マネージャー、拡張フォーム・コントロール、ツールバーとメニュー、ドラッグ・アンド・ドロップ、そしてダイレクト・リモーティングなどがあります。以上は、ExtJS が提供するコンポーネントのほんの一部に過ぎません。広範な RIA コンポーネントの数々を調べるには、必ず ExtJS Web サイトを確認してください。図 3 に、ExtJS で開発されたサンプル Web Desktop を示します。これは、このライブラリーにはいかに豊富な機能が揃っているかを示す一例です。

図 3. ExtJS のサンプル Desktop アプリケーション
グリッド・ウィンドウ、アプリケーション・ウィンドウ、タブ・ウィンドウが表示された画面

MooTools

すぐに使用できる UI コントロールとウィジェットが含まれていないという点で、MooTools は Prototype と jQuery の同類と言えます。jQuery と同じく、MooTools には限られた数のエフェクトしか組み込まれていません。高度な UX 拡張機能については、MooTools.More.js 拡張によって追加するという仕組みです。この拡張は単なる UX/UI プラグインではなく、ArrayDateHash、および String クラスに対する興味深いアドオンと、Element 拡張も追加で組み込まれています。UX 拡張機能に関して言えば、MooTools.More.js にはドラッグ・アンド・ドロップのサポート、そしていくつかの追加エフェクトが含まれています。このアドオンにはさらに、アコーディオン、ソート可能な HTML 表、スクローラー、ツールチップ、Ajax スピナー・オーバーレイなどの UI コントロールも用意されています。ただし、script.aculo.us と同じく、これらのコントロールの設計は開発者自身が実装しなければなりません。


フレームワークの比較

表 1 で、この記事で取り上げた 5 つのフレームワークで使用可能な機能を細かく比較します。

表 1. フレームワークの機能比較
PrototypejQueryYUIExtJSMooTools
最新バージョン1.6.11.4.13.003.11.2.4
ライセンスMITMIT および GPLBSD商用および GPL v3MIT
ブラウザー互換性
IE サポート6.0+6.0+6.0+6.0+6.0+
Firefox サポート1.5+2.0+3.0+1.5+2.0+
Safari サポート2.0.4+3.0+4.0+3.0+2.0+
Opera サポート9.25+9.0+10.0+9.0+9.0+
Chrome サポート1.0+1.0+未確認未確認未確認
コア機能
Ajax サポート
DOM 操作
DOM トラバース
イベント処理
JSON
セレクター
UX/UI 拡張機能
アコーディオンjQuery UIMooTools More
動画scriptaculous
自動補完scriptaculous
ブラウザー履歴scriptaculous
カレンダーjQuery UI
グラフ
ドラッグ・アンド・ドロップscriptaculousjQuery UIMooTools More
グリッドMooTools More
プログレス・バーjQuery UI
サイズ変更jQuery UI
リッチ・テキスト・エディター
スライダーscriptaculousjQuery UIMooTools More
タブjQuery UI
テーマjQuery UIMooTools More
ツリー・ビュー

その他の際立ったフレームワーク

説明を簡潔にするため、この記事ではよく使われている JavaScript フレームワークのうちの 5 つについて検討しました。しかしだからと言って、この5 つのフレームワークが最もよく使われているというわけでも、最も優れているというわけでも、最も機能が充実しているというわけでもありません。

この 5 つのフレームワークの他に名前を挙げる価値があり、検討に値する JavaScript フレームワークには以下のものがあります。

  • Cappuccino
  • Dojo
  • Glow
  • GWT
  • MochiKit
  • Qooxdoo
  • Rialto
  • Rico
  • SproutCore
  • Spry
  • UIZE

まとめ

この記事では JavaScript フレームワークの概念を紹介し、Web サイトおよび Web アプリケーションの開発になぜ JavaScript フレームワークが役立つのかを説明しました。また、フレームワークに共通する機能をいくつか取り上げ、とりわけよく使われているライブラリーでの実装例を用いてその概要を説明しました。次に、記事で取り上げた 5 つのフレームワークのそれぞれで、その一部として組み込まれているか、あるいは個別のアドオンとして提供されている UX および UI 拡張機能について説明しました。そして最後に、表によってそれぞれの機能を単純に比較し、各フレームワークに備わっているオプション、備わっていないオプションを明らかにしました。この記事の情報を基にこれらのフレームワークをさらに詳しく調べ、十分な情報を得た上で、自分や自分の開発チームに適切なフレームワークを決定してください。

参考文献

学ぶために

製品や技術を入手するために

  • Dojo ツールキットをダウンロードしてください。
  • Prototype Javascript フレームワークを入手してください。
  • jQuery を入手してください。
  • jQuery JavaScript ライブラリーをベースに作成された jQuery User Interface は、下位レベルの対話と動画、高度な効果、そして上位レベルでテーマを指定可能なウィジェットを抽象化します。
  • script.aculo.us を入手してください。
  • MooTools を入手してください。
  • Yahoo! YUI Library をダウンロードして、このライブラリーについて学んでください。
  • ExtJS を入手してください。
  • IBM ソフトウェアの試用版を使用して、次のオープンソース開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。
  • IBM 製品の評価版をダウンロードして、DB2、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を使ってみてください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Java technology
ArticleID=472083
ArticleTitle=JavaScript フレームワークの比較
publish-date=02022010