現象
先日に、eccube2の「入力内容のご確認」画面の「次へ」ボタンを押して、次の決済画面に進まない、決済モジュールの問題ではないかを含めて、調査&対応してほしいというお客様からご依頼がありました。
事前に予想し、調査の方向を決める
WEBアプリケーションにおいて、ボタンを押して、想定外の挙動が起きた場合、大体、javascriptに何らかの問題があります。
今回は、決済モジュールにも関わったようですが、決済モジュールの問題かどうかはまだ分からないため、javascriptにエラーがあるという想定で調査を進めます。
問題の現象を再現する
テストデータを作って、対象画面に進んで、「次へ」ボタンを押して、確かに次の画面に進まないことを再現しました。
調査&分析する
再現する同時に、Firefoxの(javascriptデバッグ機能、パフォーマンス、使い勝手などはとても優れる)開発ツールを開きながら、コンソールにjavascriptエラーが発生しないため、この時点で単純ミスの可能性が高く、対応難易度が下がるかもしれないことが分かりました。すぐにネットワークパネルに切り替えて、サーバーにsubmitの挙動がなかったことを確認しました。
原因を特定する
ボタンを押して、submitできない場合、html実装上に問題があるかと思って、インスペクターパネルで、「次へ」ボタンの実装を確認したところ、inputタグのtype属性の値が「button」であることを確認できました。
onclickイベントでjavascript 関数を呼び出したが、その関数の中にformのsubmitの実装がなかった。ここまでは問題の原因を特定しました。
■問題となる実装
1 2 3 4 5 |
<input type="button" onclick="return fnCheckSubmit();" value="次へ" name="next" id="next"> |
問題を解決する
submitしないのは、原因なので、inputタグのtype属性の値(button)を「submit」に修正すれば、問題を解決します。
■改修後の実装
1 2 3 4 5 |
<input type="submit" onclick="return fnCheckSubmit();" value="次へ" name="next" id="next"> |
■submitボタンがヤダな方はtype属性の改修をやめて、下記のように、fnCheckSubmit関数の中にformのsubmitメソッドを呼び出せば、大丈夫と思います。(筆者はこの方法で対応しました)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<script type="text/javascript">//<![CDATA[ var sent = false; function fnCheckSubmit() { if (sent) { alert("只今、処理中です。しばらくお待ち下さい。"); return false; } sent = true; $("#form1").submit(); // これを追加すればと思います。 } //]]></script> |
※inputタグはbuttonのまま
動作確認
改修後に、再現手順でもう一度確認したところ、javascriptエラーなどの問題がなく、次の画面に遷移することを確認できました。
疑問
無事に対応して良かったですが、一つの疑問が残っています。
eccubeさんがちゃんとテストしたはずのに、なぜ、今回の問題が発生したでしょうか。もしかして、決済モジュールを使う場合、この問題が発生するでしょうか。
取り急ぎ、オリジナル実装と比べたら、その疑問を解消しました。
■オリジナル実装
1 2 3 4 5 |
<input type="image" onclick="return fnCheckSubmit();" value="次へ" name="next" id="next"> |
■問題となる実装
1 2 3 4 5 |
<input type="button" onclick="return fnCheckSubmit();" value="次へ" name="next" id="next"> |
皆さん、お分かりになりますでしょうか。imageですよね。「input type=image」と言えば、その厄介な自動submit特性が有名ですね。
ノウハウ
昔(10数年前)、画像(image)を使って、ボタンを表すWEBアプリケーションが多かったと思います。その際に、inputタグのtype属性に「image」を設定すれば、実現できます。CSSを重視しなかった時代に、見た目(美しさ)を意識するWEBアプリケーションにとって、imageは大変便利な実現方法です。
ただし、厄介なのは、どこのドキュメントにも記載されていなくて、imageは隠れた特性を持っています。それは自動submitのことです。submitをさせないように、多くのプロジェクトは苦労していました。
(筆者が参画したプロジェクトは開発の末期でinput buttonをimageに変えましたため、想定外の挙動ばかりで、チーム全体がパニック状態になったということもありました)
今回の問題と関係ないですが、おまけに、imageのsubmitをさせない方法を紹介します。
■submitさせる/させない対応方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<script> function doit(){ //入手チェックエラーなど(submitしたくない)の場合、 return false; //submitする場合 return true; } </script> <form action="." method="post"> <input type="image" name="sample" src="sample.jpg" onClick="doit();"> </form> |
まとめ
最近のWEBアプリケーションは、imageの代わりに、CSSでボタンイメージを実現することは流行っていますので、imageの自動submit特性を知らない若い人が多いではないかと思います。
今回の問題を通して、input type=imageの自動submit特性を覚えて、今後このノウハウを活かして、問題を解決できればと思います。