CakePHP2.3以降のformヘルパーでは、モデルのバリデーションで必須項目にしてあると、HTML5の「required」属性が自動的に付加されるようになっています。
この属性が設定されていると、submitしようとしたタイミングで自動的にチェックがかかり、必須項目なのに入力がされていなければ、そこに「このフィールドは入力必須です。」といったメッセージが表示されてsubmitがかかりません。
ちなみにこれを回避するには、formヘルパーでcreateするときにオプションで「novalidate」を指定してやるとのこと。
CakePHP2.3からinputタグにhtml5のrequired属性がつくようになった - cakephperの日記(CakePHP, MongoDB)
http://d.hatena.ne.jp/cakephper/20130211/1360589926
echo $this->Form->create('Model', array('novalidate' => true));
さて今回、フォームから大きなファイルを送信しそれを処理するのに時間がかかるため、ユーザが2重でsubmitを押してしまうのを防ぐよう、クライアント側javascriptでsubmitボタンを消して、代わりに送信処理中のメッセージを出すようにしていました。
しかしそうすると、requiredな項目が入力されておらず再入力が求められた時に、submitのボタンが消えてしまっていて押せない…という問題が起きました。
そこで、requiredで引っかかった時のイベントを拾ったら、処理中メッセージを消してsubmitボタンを再度表示するようにしてみました。
まずrequiredで引っかかった場合どんなイベントが発生するのかを探しました。
これなかなか情報見つけられなかったのですが「invalid」イベントが発生するそうです。
HTML5で仕様になった入力値チェック+便利な3Tips (3/3)- @IT
http://www.atmarkit.co.jp/fwcr/design/benkyo/html5appli09/03.html
addEventListener("invalid", function() { … }, false);
ただ、この記事では「form」に対してaddEventListenerになっているのですが、実際にはそれでは動かず、各input等に対してaddEventlistenerしてやるのが正しいようです。
これは素のDOMを利用した場合なので、jQueryからも簡単に扱えないかと思い調べてみました。
例えば「$('#input1').invalid()」みたいなので呼べるのかな?と思ったのですが、探した限りでは「bind」で「invalid」イベントと結びつけるようです。
jQuery Supports HTML5 Events - jsFiddle
http://jsfiddle.net/rwaldron/GJeez/
$("input").bind("input contextmenu invalid", function(event) { … });
これでsubmitしたらsubmitボタンを消すが、requiredで引っかかった場合には再度表示するサンプルを、jQueryを使った場合とjQueryオブジェクトから素のDOMを取ってきて使った場合とで書いてみます。
<form id="form1"> <input type="text" name="text1" id="text1" required="required"> <button type="submit" id="submit1">送信</button> </form> <script> $('#submit1').click( function() { $(this).hide(); alert('消した!') } ); $('#text1').bind('invalid', function() { $('#submit1').show() } ); // jQuery //$('#text1')[0].addEventListener('invalid', function() { $('#submit1').show() }, false); // DOM </script>
しかしこれを書いてて思ったんですが、requiredのチェックはsubmitが行われる直前で行われるため、引っかかった場合はsubmitは呼ばれないのです。
なのでsubmitが本当に呼ばれた時だけsubmitを消してメッセージを表示すれば良い、ような気もしますね…
というわけで最終的な答えは
<script> $('#form1').submit( function() { $('#submit1').hide(); alert('消した!') } ); </script>
になりました。