PerlでAjax(CGI-Ajax編)?

[edit]

目次

[edit]

CGI-Ajax

CGI::AjaxはHTMLページ上に発生したJavaScriptイベントをトリガーに非同期にperlのサブルーチンをコールすることを可能にします。このために、まず、下記のようにJavaScriptのファンクション名とPerlサブルーチンのリファレンスとをマッピングさせます。

my $cjx = new CGI::Ajax( 'JSFUNC' => \&PERLFUNC );

JSFUNCはJavaScriptのファンクション名、PERLFUNCはJSFUNCにマッピングさせるPerlサブルーチンです。

次に、JSFUNCを起動するトリガー(JavaScriptイベント)をセットします。ここでは、onClickを例に示してみます。

onClick="JSFUNC(['source1','source2'], ['dest1','dest2']);"

ここまでの記述によって、onClickイベント発生時にJSFUNCが起動され、JSFUNCにマッピングされたPerlのサブルーチン(PERLFUNC)がコールされます。

JSFUNCの引数

['source1','source2'], ['dest1','dest2']

のsource1、source2、dest1、dest2はHTMLページ内のinput、およびdivのidです。

 <input type=text id=source1 />
 <input type=text id=source2 />
 <div id=dest1></div>
 <div id=dest2></div>

引数は[]でかこまれたものが二つありますが、最初の[]は入力に相当し、二つ目の[]は出力に相当します。
つまり、

onClick="JSFUNC(['source1','source2'], ['dest1','dest2']);"

と表記すると、JSFUNCへの入力としてsource1、source2が指し示すinputへの入力データを渡し、結果をdest1、dest2が指し示すdivに出力することになります。JSFUNCはPERLFUNCとマッピングされているため、source1、source2がPerlサブルーチン(PERLFUNC)の引数になり、Perlサブルーチン(PERLFUNC)の結果がdest1、dest2に返されることになります。

[edit]

もっともシンプルな例(一つの入力に一つの出力)

シンプルな例を示します。下のプログラムを適当な名前で保存し、ブラウザからCGIとして実行するとテキストボックスが表示されます。表示されるテキストボックスに文字列を入力すると(=JavaScriptのkeyupイベントが発生すると)、「[入力した文字列]が入力されました」と画面に非同期で表示します。

#!/usr/bin/perl

use strict;
use CGI;
use CGI::Ajax;
use Jcode;

my $cgi = new CGI;
my $cjx = new CGI::Ajax( 'exported_func' => \&perl_func );

print $cjx->build_html( $cgi, \&show_HTML );

sub perl_func {
        my $input = shift;
        my $output = $input . "が入力されました";
        Jcode::convert(\$output, 'utf8', 'euc');
        return $output;
}

sub show_HTML {
        my $html = <<EOHTML;
        <html>
        <body>
          何か入力してください。
          <input type="text" name="val1" id="val1" onkeyup="exported_func( ['val1'], ['resultdiv'] );"/>
          <br/>
          <div id="resultdiv"></div>
        </body>
        </html>
EOHTML
        Jcode::convert(\$html, 'utf8', 'euc');
        return $html;
}

val1上でkeyupイベントが発生するとexported_funcが起動され、exported_func()にマッピングされたperl_func()がval1のvalueを引数にしてコールされます。perl_funcはval1のvalue(=$inputに格納)を「が入力されました」という文字列と結合して(=$outputに格納)、returnします。このリターンされた$outputがexported_func()の第2引数に指定されたresultdivが指し示すdivの値として返されます。

$cjx->build_html()はCGIオブジェクトと画面のHTMLを返すサブルーチンへのリファレンスを引数にとって、Ajaxコードを組み込んだHTMLの文字列を返します。

[edit]

複数の入力に複数の出力

onClick="JSFUNC(['source1','source2'], ['dest1','dest2']);"

のような複数の入出力に対応するには、Perlのサブルーチン(PERLFUNC)で複数の値を引数で受け取り、配列で値を返せばOKです。

sub perl_func {
       my $source1 = shift;
       my $source2 = shift;
       my $output1 = "source1に" . $source1 . "が入力されました";
       my $output2 = "source2に" . $source2 . "が入力されました";
       Jcode::convert(\$output1, 'utf8', 'euc');
       Jcode::convert(\$output2, 'utf8', 'euc');
       return ($output1, $output2);
}

例えば、上のようにサブルーチンを定義すると、$source1、$source2にそれぞれsource1、source2での入力値が格納され、$output1の値がdest1に、$output2の値がdest2に返されます。

[edit]

独自のJavaScriptファンクションにPerlサブルーチン(PERLFUNC)の返り値を渡す

独自に定義したJavaScriptファンクションにPerlサブルーチン(PERLFUNC)の返り値を渡すこともできます。

 onClick="exported_func(['input1'],[js_process_func]);"

上のjs_process_funcが返り値を渡すJavaScriptファンクション名です。idを指定する時と異なり、'で括りません。('で括るとidとみなしてCGI::Ajaxは動作します)

Perlサブルーチン(PERLFUNC)が複数値(=配列)を返す場合はjs_process_func()の方でargumentsオブジェクトを利用して取得してあげる必要があります。

function js_process_func () {
  var input1 = arguments[0];
  var input2 = arguments[1];
  // 自分でgetElementByIdで出力先を特定して値をセットする必要アリ
  document.getElementById('outputdiv').innerHTML = input1 + 'と' + input2;
}
[edit]

外部のスクリプトにリクエストする

外部のスクリプトにAjaxのリクエストを飛ばして実行させることも可能です。その為には、CGI::Ajaxのコンストラクタに指定するマッピングでPerlサブルーチンリファレンスではなく、対象スクリプトのURLを指定します。

 my $url = 'scripts/other_script.pl';
 my $cjx = new CGI::Ajax( 'external' => $url );

ページ側の記述はこれまでと同様です。

 onClick="external(['input1','input2'],['resultdiv']);"

外部スクリプト(scripts/other_script.pl)ではCGIオブジェクトのparamメソッドからargsキーを用いてinput1、input2の入力を取得できます。

#!/usr/bin/perl
# scripts/other_script.plの例

use strict;
use CGI;

my $cgi = new CGI;
my @input = $cgi->param('args');

print $cgi->header();
print "input length is " . @input . " . \n";

仮に上のスクリプトをscripts/other_script.plとすると、実行結果としてinput1、input2が共に入力されていれば「input length is 2 .」という文字列がresultdivに返されます。

[edit]

GET / POST の切り替え

非同期通信を実行する時にリクエストに使うMethodをGET / POSTから選ぶことができます。

GETを使う時は

 onClick="exported_func(['input1'],['result1'], 'GET');"

POSTを使う時は

 onClick="exported_func(['input1'],['result1'], 'POST');"

というふうにJavaScriptファンクションの第3引数に指定します。

デフォルトではGETが使われます。

[edit]

参考


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

アークウェブのサービスやソリューションはこちら