« Class::DBIで複数データベースを扱う+register_cleanup | メイン | PATH_INFOと相対パス(リンク) »

HTML::Prototypeを使ったauto complete field

HTML::Prototypeを使ったauto complete fieldをCGI::ApplicationCGI::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」が&aring;&#140;&#151;&aelig;&micro;&middot;&eacute;&#129;&#147;のように変にエンコードされてしまう。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ってデモには良いけど実際使い道があまりないなぁ。