Catalystでajax (HTML::Prototypeモジュールの使い方)
changelog
- typoを修正。positionの説明で「4通り」を「44通り」と書いていたので。そんなにあるわけない。(2005/05/13)
- $prototype->form_remote_tag のオプションpostitionの説明を追加。(2005/04/30)
概要
Catalyst で作る簡単 Web アプリケーション: Feed2JS 解説 を参考にしながら、 Catalyst をいじっていたのですが、ajaxな部分を司る Catalyst::Plugin::Prototype について調べたことを、ここにメモしておきます。
まず、「prototype」という名が示すのは、「原型」という意味ではなくて、 prototypeという名のオブジェクト指向Javascriptライブラリ です。俺は最初それが分からず、「ん?何かの原型を作るようなモジュールなのか?」と悩んでました。このライブラリの実態はこんな感じです。 prototype.js
で、Catalyst::Plugin::Prototype自体は、 HTML::Prototype のメソッドをCatalystのビューから呼び出せる様にするものです。なので、Catalyst::Plugin::Prototypeの使い方を知るためには、まずはHTML::Prototypeの使い方を知る必要があります。
このHTML::Protoytypeは何をするものなのかというと、prototype.js内のajax関連の関数を呼び出すようなHTMLを手軽に生成するためのもの、ということになります。以下、HTML::Prototypeの使い方と、Catalystから呼び出す方法についてHTML::Prototypeのドキュメントを参考にしながら、実行例も交えて順に見ていきます。また、ドキュメントに載っていないものの、ソースコードから読みとれるものもできる限り記述したいと思います。
基本的なHTML::Prototypeの使い方は以下の様になります。
use HTML::Prototype; my $prototype = HTML::Prototype->new; print $prototype->define_javascript_functions;
HTML::Prototypeで利用できるメソッドは以下の通りです。
- $prototype->define_javascript_functions
- $prototype->form_remote_tag(\%option)
- $prototype->link_to_function( $name, $function )
- $prototype->link_to_remote( $id, \%options )
- $prototype->observe_field( $id, \%options)
- $prototype->observe_form( $id, \%options )
- $prototype->periodically_call_remote( \%options )
- $prototype->submit_to_remote( $name, $value, \%options )
各メソッドを順に見ていきます。
$prototype->define_javascript_functions
このメソッドはprototype.jsの内容そのものを返します。つまり、
print $prototype->define_javascript_functions;
を実行すると、以下の内容が出力されます。
<script type="text/javascript">
<!--
/* Prototype: an object-oriented Javascript library, version 1.2.0
* (c) 2005 Sam Stephenson <sam@conio.net>
*
* THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
* against the source tree, available from the Prototype darcs repository.
*
* Prototype is freely distributable under the terms of an MIT-style license.
*
* For details, see the Prototype web site: http://prototype.conio.net/
*
/*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.2.0'
}
... (省略)
これはあんまり使い道ない気がします。HTML内で、
<script type="text/javascript" src="prototype.js"></script>
としてやればいいですし、Catalystでも、
$ script/my-app_create.pl Prototype
でroot以下にprototype.jsが生成されますから。
$prototype->form_remote_tag(\%option)
このメソッドでは、xmlHttpRequestでサブミットする様なformタグを生成します。オプションとその説明は以下の通りです。
$prototype->form_remote_tag({
method => 'post',
url => '/url',
update => 'id',
position => 'Before',
type => 'synchronous',
callback => 'callback()',
});
- method
- リクエストメソッドを指定します。
- url
- submit先のURLを指定します。
- update
- xmlHttpRequestで得られたレスポンスを、どのidを持つコンテナに挿入するかを指定します。つまり、ここで指定したidに対して、prototype.jsが document.getElementById(id).innerHTML = req.responseText; みたいなことをやってくれます。
- position
-
何も指定しない場合、idで指定されたコンテナの内容をすべてresponseTextで置き換えますが、positionを指定していると、特定の位置にreponseTextを挿入します。指定できる位置は以下の4通りです。
- Before ... コンテナの直前。(コンテナの外側)
- Top ... コンテナの一番上。(コンテナの内側)
- Bottom ... コンテナの一番下。(コンテナの内側)
- After ... コンテナの直後。(コンテナの外側)
- type
- synchronousかasynchronousを指定します。デフォルトはasynchronousです。
- callback
-
xmlHttpRequestのreadyStateに応じて呼び出す関数を指定します。callbackには以下の種類があります。
- loading ... readyStateが1の時に呼び出す関数を指定します。
- loaded ... readyStateが2の時に呼び出す関数を指定します。
- interactive ... readyStateが3の時に呼び出す関数を指定します。
- complete ... readyStateが4の時に呼び出す関数を指定します。
実際にこのメソッドが吐き出すHTMLコードを見るために、
print $prototype->form_remote_tag({
url => '/url',
update => 'id',
type => 'synchronous',
loading => 'loading()',
});
というコードを実行してみると、以下の様に出力されます。
<form onsubmit=" new Ajax.Updater( 'id', '/url', { parameters: Form.serialize(this),asynchronous: 0,onLoading: function(request){loading()} } ) ; return false;">
$prototype->link_to_function( $name, $function )
このメソッドでは、$functionを呼び出す、$nameで指定したアンカーを持つリンクを生成します。実行すれば一目瞭然、ってことで、
print $prototype->link_to_function( "Greeting", "alert('Hello World!')" );
と実行すると、
<a href="#" onClick="alert('Hello World!'); return false;">Greeting</a>
というHTMLを吐きますし、
print $prototype->link_to_function( '<img src="really.png"/>', 'do_delete()' );
と実行すると、
<a href="#" onClick="do_delete(); return false;"><img src="really.png"/></a>
というHTMLを吐きます。
$prototype->link_to_remote( $id, \%options )
このメソッドでは、指定したURLに対してxmlHttpRequestでリクエストする様なリンクを返します。オプションと説明は以下の通りです。
$prototype->link_to_remote(
'anchor', {
with => 'name=value',
url => 'url',
update => 'id',
type => 'synchronous',
callback => 'callback()',
})
- anchor
- リンクのanchorを指定します。
- with
- GETのQUERY_STRINGまたはPOSTのbodyとして送信するデータを、name=valueといった形で指定します。
- その他のオプション
- $prototype->form_remote_tag(\%options)と同じです。
実際にこのメソッドが吐き出すHTMLコードを見るために、
print $prototype->link_to_remote(
'anchor',
{
update => 'id',
url => 'url',
type => 'synchronous',
} );
というコードをを実行すると、
<a href="#" onClick=" new Ajax.Updater( 'id', 'url', { asynchronous: 0 } ) ; return false;">anchor</a>
というHTMLを吐きます。
$prototype->observe_field( $id, \%options)
このメソッドでは、$idで指定されたidを持つフィールドを監視して、変更があればxmlHttpRequestでリクエストを出すようなスクリプトを返します。%optionsは$prototype->form_remote_tag(\%options)と同じです。
実際にこのメソッドが吐き出すJavascriptコードを見るために、
print $prototype->observe_field(
'field_id',
{
update => 'id',
url => 'url',
type => 'synchronous',
} );
と実行すると、
<script type="text/javascript">
<!--
new Form.Element.Observer( 'field_id', 2, function( element, value ) { new Ajax.Updater( 'id', 'url', { parameters: value,asynchronous: 0 } ) } );
//-->
</script>
というJavascriptコードを吐きます。
$prototype->observe_form( $id, \%options )
$prototype->observe_fieldと基本的に同じですが、$idで指定されたフォーム全体を監視して、変更があればxmlHttpRequestでリクエストを出すようなスクリプトを返します。%optionsは$prototype->form_remote_tag(\%options)や他と同じです。
実際にこのメソッドが吐き出すJavscriptコードを見るために、
print $prototype->observe_form(
'form_id',
{
update => 'id',
url => 'url',
});
と実行すると、
<script type="text/javascript">
<!--
new Form.Observer( 'form_id', 2, function( element, value ) { new Ajax.Updater( 'id', 'url', { parameters: value,asynchronous: 1 } ) } );
//-->
</script>
というJavascriptコードを吐きます。
$prototype->periodically_call_remote( \%options )
このメソッドでは、xmlHttpRequestによるサーバへのリクエストを、一定間隔で呼び出すようなスクリプトを返します。$options->{frequency}で時間を秒間隔で指定します。(デフォルト2秒。)他のオプションについては、他のメソッドと同様です。
print $prototype->periodically_call_remote({
update => 'id',
url => 'url',
});
と実行すると、
<script type="text/javascript">
<!--
new PeriodicalExecuter( function () { new Ajax.Updater( 'id', 'url', { asynchr
onous: 1 } ) }, 10 );
//-->
</script>
というJavascriptコードを吐きます。
$prototype->submit_to_remote( $name, $value, \%options )
このメソッドでは、$name, $valueで指定されたnameとvalueをxmlHttpRequestでsubmitするボタンを生成します。%optionsは他のメソッドと同様です。
実際にこのメソッドが吐き出すHTMLコードを見るために、
print $prototype->submit_to_remote(
'name',
'value',
{
update => 'id',
url => 'url',
});
と実行すると、
<input type="button" name="name" value="value" onsubmit=" new Ajax.Updater( 'id', 'url', { asynchronous: 1 } ) ; return false;"/>
というHTMLコードを吐きます。
Catalystのビューから呼び出す方法
HTML::Prototypeのメソッドを、Catalystのビューから呼び出すためには、テンプレートに以下の様に記述します。
[% c.prototype.observe_field( 'editor', {
url => 'url',
with => "'body='+value",
update => 'view'
}) %]
ご覧頂くと分かるように、オプションの渡し方は、perlでのメソッド呼び出しと何ら変わりありませんので、詳細は省きます。(手抜きですんません。HTML::Prototypeの説明で力尽きました。)