3つのを連動させる [Perl][Catalyst][Prototype][Ajax]

3つの<select>を使って、次のようなことをしたい。
最初のselectで地方名を選ぶと、2番目の<select>に県名が表示され、2番目の<select>で県名を選ぶと、3番目の<select>に区市町村名が表示される。これを画面遷移なしで行いたい。

地方名→県名の2段連動なら、prototype.jsのobserve_fieldを使う。catalystからprototypeを使うやり方はこちらが参考になりました。
http://blog.mizzy.org/articles/2005/09/10/htmlPrototype

で、具体的にはtemplateに下記のように書き加える。

<head>
〜中略〜
<script type="text/javascript" src="/prototype.js"></script>
〜中略〜
</head>
<body>
〜中略〜
<select id="Region" size=20 style="width:150px;" multiple>
       <option value="1">北海道
       <option value="2">東北
       <option value="3">関東
               :
               :
</select>
[% c.prototype.observe_field( 'Region', {
               update  => 'div_pref'
               url     => c.req.base _ 'list/pref',
               with    => "'body='+value",
}) %]
<div id="div_pref">
<select id="pref" size=20 style="width:150px;" multiple>
</select>
</div>
〜中略〜
</body>

これで、地方を選ぶと、list/prefアクションが呼ばれるので、下記のようにコントローラで地方名を受け取り、それを元に県名リストを作成して、置き換える<select>を返す。

my @regions     = split(/,/, $c->req->param('Region'));

テンプレートはこう。(<option>だけ渡せばいいような気がするけど、<select>丸ごと置き換えないとうまく行かなかったので、こうなってます)

<select id="pref" size=20 style="width:150px;" multiple>
[% FOREACH i IN results %]
<option value=[% i.pref_id %]>[% i.pref_name %]</option>
[% END %]
</select>

しかし、地方名→県名→区市町村名の3段連動となると、うまく動かなかった。単純に[% c.prototype.observe_field %]を増やすだけではだめなようだ。いろいろ調べてみたが、いまいちスパッと答えが見つからず。
仕組みとしては、おそらくDOMツリーが構築された後に、<div id="div_pref">の中身をAjaxで書き換えているが、observe_fieldが監視しているのは書き換えられる前のDOMツリーなので、反応しないんジャマイカAjaxの基礎ができてないので、用語とかいろいろ間違ってるかもしれないが。

で、試行錯誤した結果、次のようにすることで目的は達成できた。
2回目のobserve_field(県名の変化の検知)が、1回目のobserve_field(地方名の変化の検知)のときに発動するように、[% c.prototype.observe_field %]が出力するスクリプトをまねして、直にjavascriptを書いた。

<head>
〜中略〜
<script type="text/javascript" src="/prototype.js"></script>
〜中略〜
</head>
<body>
〜中略〜
<select id="region" size=20 style="width:150px;" multiple>
       <option value="1">北海道
       <option value="2">東北
       <option value="3">関東
               :
               :
</select>
<script type="text/javascript">
<!--
function Observe_pref(element, value) {
       new Ajax.Updater(
               'div_cities',
               '[% c.req.base %]list/cities',
               {
                       parameters: 'pref='+value,
                       asynchronous: 1,
                       onComplete: function(request) {
                               // ここに付け足したら4段目もいけるかな?
                       }
               }
       )
}
function Observe_region(element, value) {
       new Ajax.Updater(
               'div_pref',
               '[% c.req.base %]list/pref',
               {
                       parameters: 'region='+value,
                       asynchronous: 1,
                       onComplete: function(request) {
                               new Form.Element.EventObserver( 'pref',
                                       function( element, value ) {
                                               Observe_pref(element, value);
                                       }
                               );
                       }
               }
       )
}
new Form.Element.EventObserver( 'region',
       function( element, value ) {
               Observe_region(element, value);
       }
);
//-->
<div id="div_pref">
<select id="Pref" size=20 style="width:150px;" multiple>
</select>
</div>
<div id="div_cities">
<select id="City" size=20 style="width:150px;" multiple>
</select>
</div>〜中略〜
</body>


以下、参考にさせていただいたサイト。
http://plugins.jquery.com/project/DependentSelectbySilVeR
2段連動、のような気がする。試していない。
2009-05-22
県名→区市町村名の2段連動の例。
JavaScript(ajax) prototype.js によるプルダウン(Selectボックス)2段連動 ( ネットサービス ) - Webメディア開発日記 - Yahoo!ブログ
2段連動。
http://news.kapi.jp/log/view/2153
Form.EventObserverのイベントハンドラを設定したり解除したりについて。
http://osdir.com/ml/web.catalyst.general/2006-02/msg00182.html

Changing Select element content on the fly
javascript