日記
form.onsubmitとEvent.observeに関する実験Edit

<script type="text/javascript" src="prototype.js"></script>
<form id="test" onsubmit="return formOnSubmit();">
<input type="submit">
</form>
<script type="text/javascript">
function formOnSubmit()
{
alert('formOnSubmit');
return false; /* A */
}
Event.observe('test', 'submit', function() {alert('EventObserve'); return false; /* B */}, false);
</script>

上記のようなコードを、Firefox 1.5.0.1、IE 6.0.2900.2180、Opera 8.5でテスト。

イベントハンドラー実行順序はどれも、form.onSubmit→Event.observeの順序。ただし、form.onSubmitの戻り値がfalseであっても、必ずEvent.observeした関数も呼ばれてしまう。

つまり、もしform.onSubmitのコードがバリデーションロジックで、バリデーションでエラーがあったのでfalseを返したとしても、その後に続くEvent.observeした関数=Ajaxリクエストコールは呼ばれてしまうし、Event.observeした関数には、バリデーションロジックの戻り値は伝わってこない。HTML_QuickFormみたいに、alertでエラーメッセージを表示するバリデーションロジックを出力する場合は、単純にEvent.observeしてAjaxリクエストコードを追加するパターンは使えない*1

ちなみに、A、Bの戻り値をいろいろ変えて試してみたところ、そのあたりの処理にはブラウザ互換性がないことが分かった。

A:true/B:trueA:true/B:falseA:false/B:trueA:false/B:false
Firefox止まらない止まる止まる止まる
IE止まらない止まる止まらない止まる
Opera止まらない止まらない止まる止まる

Firefoxはどちらかがfalseだったら、submit動作が止まる。IEは最後に実行されたイベントハンドラーがfalseを返したときのみ、submit動作が止まる。Operaはform.onsubmitでfalseを返したときのみ、submit動作が止まる。なんだか面倒くさいなー。

ちなみに、

Event.observe('test', 'submit', function(event) {alert('EventObserve'); Event.stop(event);}, false);

なんてしちゃえば、すべてのブラウザでsubmit動作が止まったんで、自分のコードで確実にsubmit動作を止めたければ、Event.stopを使えばいいのかな。

で、トータルでどうすればいいのかいろいろ試行錯誤して、

var currentHandler = $('test').onsubmit;
$('test').onsubmit = undefined;
Event.observe('test', 'submit', function(event) {
if ((typeof currentHandler == 'function') && (!currentHandler())) {Event.stop(event);return;}
alert('EventObserve');
Event.stop(event);
}, false);

なんて感じで、デフォルトのonsubmitを強引に後から追加したイベントハンドラーの中で実行し、その結果によって後から追加したイベントハンドラーのメイン処理を実行するかどうか分岐できるようにしてみたんだけど、FirefoxとOperaではこの方法でいけるんだけど、IEでは思ったように動いてくれないなー。

でも、どうにかしたいんだったら、こういう方向のアプローチくらいしかない気がする。JavaScriptのイベントハンドラー周りの実装っていまいち理解できていないから、その辺をちょっとお勉強してから、もう一度チャレンジしてみるか。

*1 Event.observeした関数内でもう一度バリデーションロジックを呼んだら、エラーがあったときに2回もalertが表示されてうざい

Published At2006-03-11 00:00Updated At2006-03-11 00:00