| デベロッパー | 2007年1月16日 10:00 |
|
JavaScriptを利用してフォームの二重送信を防止する 著者: Scott Mitchell オリジナル版を読む ▼2007年1月16日 10:00 付の記事 ■海外internet.com発の記事 はじめにユーザーがフォームの送信ボタンをクリックすると、ブラウザは指定されたURLのWebサーバーに要求を送ります。すると、Webサーバー側でユーザーの入力が処理され、入力に基づいて何らかのアクションが実行されます。例えばデータベースレコードが追加されたり、電子メールが送信されたりします。問題は、ユーザーがフォームを送信しても、サーバーからの応答がなかなか返らない場合です。ユーザーはクリックが「効かなかった」と考えて、何度も送信ボタンを押してしまうことがあります。その結果、フォームが二重に送信されて、2つのデータベースレコードが追加されたり、2通の電子メールが送信されたりする可能性があります。 先日、ASP101.comに掲載されているある豆知識が目にとまりました。「Stop Users from Double Clicking(ユーザーによる二重クリックを防止する)」と題するその豆知識では、フォームの送信ボタンにちょっとしたJavaScriptを追加し、ユーザーがフォームを2回以上送信できないようにする方法が紹介されていました。この方法は、ボタンのクライアント側 私のプロジェクトでは、いつももう少し複雑な別の方法を使っています。単に送信ボタンを無効にするのではなく、画面を「フリーズ」させて、データが処理中であることを示すメッセージを表示するという方法です。個人的には、フリーズした画面のルックアンドフィールの方が気に入っています。この方が、データがサーバーに送信されて処理中であることがよく分かるからです。さらに、ユーザーがページ上の他の送信ボタンをクリックするのを防ぐこともできます。本稿では、この2種類の方法について説明します。 クリックされたボタンを無効にする 多くのWebサイトでは、クリックされた時点で送信ボタンを無効にすることによって、ユーザーがフォームを二重に送信できないようにしています。通常は送信ボタンを無効にすると共に、ボタンのラベルを初期値(「送信」など)から別の値(「送信済み」など)に変更して、アクションが実行されたことを示します。ラベルを変更してボタンを無効にするには、ボタンのクライアント側 <script> function DisableButton(b) { b.disabled = true; b.value = ’Submitting’; b.form.submit(); } </script> <p> Click the button to see how it can be disabled and have its text changed when clicked... </p> <p> <input type="submit" name="SubmitButton" id="SubmitButton" value="Submit" onclick="DisableButton(this);" /> </p> この 無効になったボタンと、フォームの送信時に送信されるデータ
警告:ブラウザはフォームの送信時に、無効に設定されているコントロールのデータを送信しません。この例の送信ボタンは、クリックされた時点でJavaScriptによって無効に設定されるため、ブラウザは送信ボタンがクリックされたという情報をフォームの送信に含めません。このため、ASP.NETを使用している場合は、対応するButton Webコントロールの
Clickイベントが起動しなくなります。送信ボタンのクリックによってポストバックが発生したということがASP.NETエンジンに通知されないからです。これが問題になる場合は、次のどちらかの方法を使用します。
フォームの送信時にページを「フリーズ」させる 商用のWebアプリケーション(FogBugzなど)には、フォームの送信時に画面を「フリーズ」させて、フォームの二重送信を防いでいるものがあります。具体的には、ページ上の他のすべての要素の前面に、絶対位置で指定された要素(通常は 最初に、フリーズした画面の外観を指定するいくつかのカスケードスタイルシート(CSS)クラスを定義します。次の3つの
<div>要素を「非表示」にして、ページを操作できるように(つまりフリーズしていない状態に)します。フリーズした画面を表す要素は、実際にはフルスクリーンの
<div>要素であり、その中にメッセージ(「要求を処理しています」など)を表示する<div>要素が含まれています。このCSSクラスは、外側の<div>の設定を定義します。内側の
<div>要素のスタイル設定を指定します。この要素は、ユーザーにメッセージ(「要求を処理しています」など)を表示します。 さらに、内側と外側の まずCSSクラスから始めましょう。 <style type="text/css"> .FreezePaneOff { visibility: hidden; display: none; position: absolute; top: -100px; left: -100px; } .FreezePaneOn { position: absolute; top: 0px; left: 0px; visibility: visible; display: block; width: 100%; height: 100%; background-color: #666; z-index: 999; filter:alpha(opacity=85); -moz-opacity:0.85; padding-top: 20%; } .InnerFreezePane { text-align: center; width: 66%; background-color: #171; color: White; font-size: large; border: dashed 2px #111; padding: 9px; } </style> CSSクラスに加えて、ページに <div align="center" id="FreezePane" class="FreezePaneOff"> <div id="InnerFreezePane" class="InnerFreezePane"> </div> </div> 次に、ブラウザをウィンドウの上部にスクロールさせ( <script language="JavaScript"> function FreezeScreen(msg) { scroll(0,0); var outerPane = document.getElementById(’FreezePane’); var innerPane = document.getElementById(’InnerFreezePane’); if (outerPane) outerPane.className = ’FreezePaneOn’; if (innerPane) innerPane.innerHTML = msg; } </script> <p> <input type="submit" name="SubmitButton" id="SubmitButton" value="Submit" onclick="FreezeScreen(’Your Data is Being Processed...’);" /> </p> ![]() 画面をフリーズさせるこの方法には、いくつかの欠点や積み残しがあります。例えば、画面は実際にはフリーズしていません。ユーザーは画面をスクロールしたり、外側の また、この方法は多種多様なブラウザで十分にテストされているわけではありません。IE 6、FireFox 1.5、およびOpera 9.0(半透明の設定を除く)では機能しますが、古いブラウザに対応しているかどうかは分かりません。 このようにいくつか欠点はあるものの、私のプロジェクトではこの方法がうまく機能しており、読者にもある程度役に立つことと思います。 では、ハッピープログラミング! 著者紹介Scott Mitchell(Scott Mitchell)
|