HTML::Prototypeを使ったauto complete fieldをCGI::ApplicationとCGI::Application::Plugin::HTMLPrototypeを利用して組んでみた。候補データの文字化け対策も。
HTML::Prototype説明は、mizzy.orgさんのエントリが詳しい。
すでに珍しくもないauto completeの動作サンプルは以下
http://nomadscafe.jp/test/autocompletefield/app.cgi/
市区町村名を途中まで入力すると候補がでてくる。
CGI::Applicationで
use base qw(CGI::Application);
use CGI::Application::Plugin::TT;
use CGI::Application::Plugin::HTMLPrototype;
としてTTとHTMLPrototypeプラグインを利用します。
上の入力フォームのあるページは、
$self->tt_process('index.tmpl.html',{proto=>$self->prototype});
な感じで出力します。方法はなんでも。テンプレートにはJavaScriptのコードを書き出す部分をいくつか追加。headの中に
<head>
...
[% proto.define_javascript_functions %]
[% proto.auto_complete_stylesheet %]
...
</head>
フォームの部分は
<input name="textf" type="text" id="textf" size="20" autocomplete="off">
<div id="textf_auto_complete" class="auto_complete"></div>
[% proto.auto_complete_field('textf',{url=>'autocompresults'}) %]
このdivの中に候補が描画されます。3行目はまたJavaScriptのコードを書き出す部分で、
<script type="text/javascript">
new Ajax.Autocompleter( 'textf', 'textf_auto_complete', 'autocompresults',{ })
</script>
になります。3つ目の引数がオートコンプリートのデータを返すURLで今回の/test/autocompletefield/app.cgi/の相対パスの/test/autocompletefield/app.cgi/autocompresultsにアクセスします。表示の方はこれで完了。
オートコンプリートのデータは、
<ul>
<li>候補1</li>
<li>候補2</li>
<li>候補3</li>
</ul>
という形式で返すのですが、HTML::Prototypeにはauto_complete_resultというメソッドが用意されていて、配列を渡すと上の形式に整えてくれるのですが、これがうまく動いてくれません。マルチバイト文字が化けてしまいます。「候補1」が北海道のように変にエンコードされてしまう。HTML::Prototypeの中でHTML::Elementを利用しているのでHTML::Elementの問題かもしれない。Perl
5.8ならうまく行くのかなぁ。。
なのでこの部分を自分で書き直した。@retが候補の配列として、生に返す
return join("?n","<ul>",map{"<li>$_</li>"} @ret,"</ul>");
これはSafari以外ではOKでした。Safariに対応させるためには、HTML::ElementがエンコードをしているのをヒントにしてHTML::Entities::Numberedで変換してみたらOKでした。
return join("?n","<ul>",map{"<li>" . HTML::Entities::Numbered::name2hex($_) . "</li>"} @ret,"</ul>");
Macでは日本語変換のタイミングであまり気分よく候補がでませんが、文字化けもないので使えるようになりました。
ソースはここからみれます。
auto completeってデモには良いけど実際使い道があまりないなぁ。