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.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が生成されますから。
このメソッドでは、xmlHttpRequestでサブミットする様なformタグを生成します。オプションとその説明は以下の通りです。
$prototype->form_remote_tag({
method => 'post',
url => '/url',
update => 'id',
position => 'Before',
type => 'synchronous',
callback => 'callback()',
});
実際にこのメソッドが吐き出す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;">
このメソッドでは、$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を吐きます。
このメソッドでは、指定したURLに対してxmlHttpRequestでリクエストする様なリンクを返します。オプションと説明は以下の通りです。
$prototype->link_to_remote(
'anchor', {
with => 'name=value',
url => 'url',
update => 'id',
type => 'synchronous',
callback => 'callback()',
})
実際にこのメソッドが吐き出す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を吐きます。
このメソッドでは、$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_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コードを吐きます。
このメソッドでは、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コードを吐きます。
このメソッドでは、$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コードを吐きます。
HTML::Prototypeのメソッドを、Catalystのビューから呼び出すためには、テンプレートに以下の様に記述します。
[% c.prototype.observe_field( 'editor', {
url => 'url',
with => "'body='+value",
update => 'view'
}) %]
ご覧頂くと分かるように、オプションの渡し方は、perlでのメソッド呼び出しと何ら変わりありませんので、詳細は省きます。(手抜きですんません。HTML::Prototypeの説明で力尽きました。)