Rails 2.2.2 の submit_tag で disable_with と confirm を同時に指定すると confirm が効かない
Rails の submit_tag には submit ボタンクリック時にボタンを disable にして二重送信を防止する disable_with オプションがあります。
<%= submit_tag '送信', :disable_with => '送信中です...' %>
ところが、Rails 2.2.2 では生成される JavaScript の不具合で、IE では上手く動作してくれません(確認したのは Vista の IE7 です)。
この問題については、以下の URL で対処法について詳しく記事を書いて下さっている方がいたお陰で、あっさり回避することができました。
submit_tagの :disable_withオプション - satake7’s memo
http://d.hatena.ne.jp/satake7/20090122
ただ、今度は disable_with と同時に、確認ダイアログを出す confirm オプションを指定した場合、確認ダイアログが出てくれません。
<%= submit_tag '送信', :disable_with => '送信中です...', :confirm => '送信してもよろしいですか?' %>
どうやらこのダイアログの出ない現象は、 IE のみではなく、Firefox(3.0.13)、Google Chrome(2.0.172.39) でも同様のようです。
この問題の為だけに Rails のバージョンを上げるというのも微妙なので、回避方法を調べていたところ、2.2.2 以上のバージョンでは既に修正されているようでした。
Commit 77f7d98e38dddf72890c80b4e4b2e088bb76d111 to rails's rails - GitHub
http://github.com/rails/rails/commit/77f7d98e38dddf72890c80b4e4b2e088bb76d111
修正内容的に satake7 さんの修正と合わせて適用できそうだったので、以下のように submit_tag をオーバーライドしました。
application_helper.rb に以下のコードを入れています。
module ActionView module Helpers module FormTagHelper def submit_tag(value = "Save changes", options = {}) options.stringify_keys! if disable_with = options.delete("disable_with") disable_with = "this.value='#{disable_with}'" disable_with << ";#{options.delete('onclick')}" if options['onclick'] # :disable_with オプションの IE 不具合のための修正 #options["onclick"] = "if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }" #options["onclick"] << "else { hiddenCommit = this.cloneNode(false);hiddenCommit.setAttribute('type', 'hidden');this.form.appendChild(hiddenCommit); }" options["onclick"] = "this.setAttribute('originalValue', this.value);this.disabled = true;#{disable_with};" options["onclick"] << "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());" options["onclick"] << "if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" end if confirm = options.delete("confirm") # confirmオプションとdisabled_withオプションの併用を可能とするための修正 # options["onclick"] ||= '' # options["onclick"] << "return #{confirm_javascript_function(confirm)};" options["onclick"] ||= 'return true;' options["onclick"] = "if (!#{confirm_javascript_function(confirm)}) return false; #{options['onclick']}" end tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) end end end end
これで無事期待通りの動作をしてくれるようになりました。
ちなみに、手元でサンプルを書いて確認したところ、どちらの現象も Rails 2.3.3 では発生しませんでした。