PrototypeでAJAX開発を効率化はじめにPrototypeのホームページには、「Prototypeは動的なWebアプリケーションの開発を簡易化することを目的としたJavaScriptフレームワークである」と書かれています。Prototypeは、クラス主導の開発や継承など多くのオブジェクト指向の手法を使ってJavaScriptアプリケーションを開発できるようにすることで、その目的を完全に果たしています。事実、このフレームワークには役に立つ機能が数多く用意されており、一度使い始めたら、どのアプリケーションの開発にも利用したくなります。 Prototypeの最大の特徴は、その機能豊富なAJAX(Asynchronous JavaScript and XML)ライブラリにあり、これによって、JavaScriptを介してサーバの非ブロック呼び出しを行うという人気のWeb開発手法を簡単に取り入れることができます(昨年度のAjaxian.com 2006 Surveyでは、Prototypeは最も人気の高いAJAXフレームワークという評価を受けました)。もちろん、Prototypeで実現できることはすべて、Prototypeのベースである普通のJavaScriptでも実現できます。しかし、わざわざ仕事を増やす必要はありません。例えば、同じタスクを行うのに とはいえ、Prototypeは巨大なフレームワークなので、1回では説明しきれません。そこで、ここではごく一部の重要な機能だけを紹介します。フレームワーク全体を深く理解するには、ソースコードを見てください。基本な仕組みを知るにはソースコードを見るのが一番であり、必要に合わせて修正を加えることもできます。 便利な関数 WebアプリケーションでPrototypeを使うには、まず最新のバージョンをダウンロードします(本稿執筆時の最新バージョンは1.4.0)。実際に必要なファイルは「prototype.js」だけで、次のように <script type="text/javascript" src="yourPath/prototype.js"></script> 先ほど取り上げた <!-- HTML --> <div id="firstElem">First element’s content</div> <div id="secondElem">Second element’s content</div> // JavaScript var elems = $("firstElem", "secondElem"); alert(elems[1].innerHTML); //displays "Second element’s content" もう1つの実に役に立つショートカット関数は、フォームフィールドIDを取得してフィールド値を返す <!-- HTML --> <select name="language" id="language"> <option value="JS" selected="selected">JavaScript</option> <option value="Java">Java</option> <option value="C#">C#</option> <option value="Ruby">Ruby</option> </select> // JavaScript var langValue = $F("language"); alert(langValue); //displays "JS" オブジェクト指向(Object-Oriented:OO)のJavaScriptPrototypeでは、OOスタイルに非常によく似たJavaScriptコードを作成することもできます。例えば、次のクラス定義を見てみましょう。 // Class definition var Person = Class.create(); // Class methods Person.prototype = { //Constructor initialize : function(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; }, //method #1 toString : function() { return this.firstName + " " + this.lastName + ", " + this.age; }, //method #2 displayFirstName : function() { alert(this.firstName); } }; var myPerson = new Person("Alessandro", "Lacava", 30); alert(myPerson.toString()); //displays "Alessandro Lacava, 30" 見ての通り、コンストラクタは(慣例により) また、Prototypeでは、 「this」の参照先が期待どおりではない場合 既にご存知のように、JavaScriptの関数は本格的なオブジェクトです。PrototypeはJavaScriptの <!-- HTML --> <div id="elem">Click Here</div> // JavaScript var person = new Person("John", "Brown", 20); $("elem").onclick = person.displayFirstName; ここでの目的は、ユーザーが「Click Here」をクリックしたときにファーストネーム(John)を表示することです。しかし、クリックしてみても、undefinedが表示されてしまいます。なぜかと言うと、 問題は、
$("elem").onclick = person.displayFirstName.bind(person);
これで、 Prototypeによる反復 Prototypeでは、配列の反復処理に役に立つメソッドを備えた var languages = [’JavaScript’, ’Java’, ’C#’, ’PHP’, ’C++’, ’Ruby’]; for(var i = 0; i < languages.length; i++) { alert(languages[i]); } これを var languages = [’JavaScript’, ’Java’, ’C#’]; languages.each( function(value, index) { alert(value); } );
languages.each(
function(value)
{
alert(value);
}
);
// it displays Java and JavaScript
languages.grep(/Java.*/, function(value)
{
alert(value);
}
);
このコードは、「Javaという単語から始まるすべての要素を選択し、見つかった各項目を表示する」という意味です。 複雑なフィルタ処理が必要なければ、次のように単に var prices = [10, 12, 25, 28, 50, 100]; // lowPrices = [10, 12, 25] var lowPrices = prices.select( function(value) { return value <= 25; } ); この例では、イテレータ関数がtrueを返す要素を選択します。 有益なメソッド Prototypeでは、
次に例を示します。 <!-- HTML --> <div id="elem"> Click Here </div> //Javascript Event.observe($("elem"), "click", displayAlert, false); function displayAlert() { alert("You clicked the element"); } 要素の監視を中止するには、次のように Event.stopObserving($("elem"), "click", displayAlert, false); もう1つの役に立つオブジェクトは <!-- HTML --> <input type="button" value="Click here" onclick="javascript:Element.toggle(’toggable’)"> <div id="toggable"> You can toggle me by clicking the button above. </div> さらに、要素を表示するための これで、AJAXによるプログラミングの準備が整いました。Prototypeには、Web 2.0のアプリケーションやサイトの開発に便利なツールが数多く用意されています。 Prototypeを利用したAJAX開発 AJAXの柱は、非同期の要求をサーバに送信する <!-- HTML --> <div id="myElem"> </div> // JavaScript new Ajax.Updater( "myElem", "page.htm", { onFailure : function() { alert("An error occurred"); } } ); このようにわずか数行で「page.htm」の中味を取得し、それを new Ajax.Updater( "myElem", "component.php", { parameters : "param1=value1¶m2=value2", method : "post", onFailure : function() { alert("An error occurred"); } } ); この場合、パラメータはクエリ文字列として渡されます。また、
もう1つの役に立つクラスは new Ajax.PeriodicalUpdater( "myElem", "newsProvider.php", { frequency : 5, decay : 2 } ); 1つ目と2つ目のパラメータの意味は サーバが、HTMLコードではなくXMLやJSONなどの他のデータ形式を返す場合は、別の強力なクラス new Ajax.Request( "component.php", { onSuccess : processResponse, onFailure : notifyFailure, parameters : "param1=value1¶m2=value2" } ); function processResponse(xhrObject) { alert("The response is: " + xhrObject.responseText); } function notifyFailure() { alert("An error occurred!"); } このコードでは、いくつかのパラメータを使ってサーバへの非同期要求を行います。応答が成功した場合は、 もう1つよく目にするのが、AJAXアクティビティがあると必ず通知(またはイメージ)を表示するタスクです。これは、要求の実行に時間がかかる場合に非常に役に立ちます。まさにこれを実現するのが <!-- HTML --> <div id="loading" style="visibility: hidden;"> <img src="loading.gif" /> </div> // JavaScript Ajax.Responders.register( { onCreate : displayLoading, onComplete : hideLoading } ); function displayLoading() { Element.show("loading"); } function hideLoading () { Element.hide("loading"); } この例では、AJAX呼び出しが始まると直ちにGIFが表示されます。応答を受け取ると、ロード中のGIFは非表示になります。 AJAX開発に役立つ機能 基本的に、AJAXではサーバに要求を送って応答を受け取るという処理を行います。この場合、要求と一緒に、クエリ文字列の形式(つまり、 <!-- HTML --> <form id="myForm" name="myForm"> First Name: <input type="text" name="firstName" id="firstName" /> <br /> Last Name: <input type="text" name="lastName" id="lastName" /> <br /> Gender: <br /> <input type="radio" name="gender" id="gender" value="M" checked="true"/> Male <br /> <input type="radio" name="gender" id="gender" value="F" /> Female <br /> <select id="state" name="state" multiple> <option value="ALA">Alabama</option> <option value="CAL">California</option> <option value="FLO">Florida</option> </select> <br /> <input type="button" name="clickButton" id="clickButton" value="Click Me" onclick="displayQueryString()" /> </form> // JavaScript function displayQueryString() { var qs = Form.serialize($("myForm")); alert(qs); } このフォームに私の個人的な情報を入力し、stateフィールドに「California」を指定してみたところ、図1の画面が表示されました。 図1 Form.serialize関数 ![]() 簡単かつ簡潔です。また、複数選択も可能であり、複数の値を選択した場合でも、Prototypeが正しいクエリ文字列の組み合わせを自動的に処理してしてくれます。例えば、前述のフォームで「California」と「Florida」を選択した場合は、次のクエリ文字列が返されます。 firstName=Alessandro&lastName=Lacava&gender=M&’’state=CAL&state=FLO’’
では、フォームではなくオブジェクトをシリアライズしたい場合はどうしたらよいでしょうか。当然、Prototypeはこのことも考えています。次のコードを見てみましょう。 // create the object var obj = { firstName : "Alessandro", lastName : "Lacava", gender : "M", state : "CAL" }; // get a query string from it var qs = $H(obj).toQueryString(); alert(qs); このコードの結果は図1と同じです。このコードで重要な役割を果たすのが ここまでPrototypeの数々の優秀な機能を紹介してきましたが、必要に合わせてソースコードを修正できることを忘れてはなりません。例えば、前述したとおり、
Form.Element.Serializers = {
input: function(element) {
switch (element.type.toLowerCase()) {
case ’submit’:
case ’hidden’:
case ’password’:
case ’text’:
return Form.Element.Serializers.textarea(element);
case ’checkbox’:
case ’radio’:
return Form.Element.Serializers.inputSelector(element);
}
return false;
},
:
:
:
上位ライブラリの基盤としてのPrototypePrototypeが優れたフレームワークであるということは、Prototypeをベースとして開発された上位ライブラリがあることからも分かります。このような上位ライブラリで最も有名なのが、ScriptaculousとRicoです。どちらもUI開発に使用され、AJAXを完全にサポートしています。 これらのライブラリの特徴を知るため、Scriptaculousのダウンロードページから最新のバージョンをダウンロードしましょう(本稿執筆時の最新バージョンは1.6.5で、アーカイブに含まれているPrototypeの使用バージョンは1.5.0_rc1)。必要なファイルは「prototype.js」「scriptaculous.js」「builder.js」「effects.js」「dragdrop.js」「slider.js」「controls.js」です。これらのファイルをディレクトリ(「scripts」など)に入れます。 Scriptaculousを使うには、最初の2ファイルだけをインクルードします。 <script src="./scripts/prototype.js" type="text/javascript"></script> <script src="./scripts/scriptaculous.js" type="text/javascript"> </script> その他のファイルは「scriptaculous.js」によって自動的にインポートされます。Scriptaculousは、アニメーション効果、ドラッグ&ドロップ、AJAXのコントロール、DOMのユーティリティなどを含む、リッチなUIライブラリです。次に、アニメーション効果の例を示します。 <!-- Pulsate Effect --> <div id="pulsateTest" style="border: 1px solid #0000ff; width: 100px;" onclick="new Effect.Pulsate($(’elemToShow’))"> Click to see the pulsate effect </div> <br /><br /> <!-- Puff Effect --> <div id="puffTest" style="border: 1px solid #0000ff; width: 100px;" onclick="new Effect.Puff($(’elemToShow’))"> Click to see the puff effect </div> <br /><br /> <div id="elemToShow" style="width: 200px; border: 1px solid red;"> This element was created to show some of the Scriptaculous animation effects. </div> Ricoも、AJAX開発に役立つUIライブラリです。本稿執筆時の最新バージョンは、Prototype 1.4.0をベースとする1.1.2でした。このライブラリはRicoのWebサイトからダウンロードできます。Scriptaculousと同様、Ricoを使うにはWebページに次の2つのインクルードが必要になります。インクルードするファイルが「scripts」フォルダに入っている場合は、次のように指定します。 <script type="text/javascript" src="./scripts/prototype.js"></script> <script type="text/javascript" src="./scripts/rico.js"></script> AJAXやドラッグ&ドロップなどの素敵な機能のほか、Ricoには非常におもしろいシネマ効果も用意されています。例えば、丸みのあるボックスの中にコンテンツを表示したいと思ったことはありませんか? Ricoならこれを簡単に実現できます。次に例を示します。 <!-- Round Effect --> <div id="roundTest" style="border: 1px solid #0000ff; width: 100px;" onclick="Rico.Corner.round($(’elemToRound’))"> Click to round the div </div> <br /><br /> <div id="elemToRound" style="background-color: #0000ff; color: #ffffff; width: 200px;"> This element was created to round its corners using the Rico.Co 「Click to round the div」をクリックすると、図2が表示されます。 図2 丸みのあるボックス ![]() もちろん、Ricoにも、すべての効果をカスタマイズするためのオプションが数多く用意されています。このライブラリの詳細については、Ricoのデモページをご覧ください。 PrototypeのパワーPrototypeフレームワークがいかに強力か、ご理解いただけたことと思います。非常に優れているからScriptaculousやRicoなどの素晴らしいUIライブラリの基盤として利用されているのです。Prototypeの機能をすべて身に付ければ、後は皆さんのイマジネーションだけで、次世代のWeb 2.0アプリケーションを簡単に実現することができます。 著者紹介Alessandro Lacava(Alessandro Lacava)
イタリアを活動拠点とするソフトウェア開発者、テクニカルライター。Javaと.NETテクノロジ、Webアプリケーション、通信システムを得意分野とする。通信エンジニアリングの資格を保有。連絡先については個人のWebサイトを参照。
|