サーバーが処理するのに少し時間がかかるフォームがあります。ユーザーがボタンをもう一度クリックしてフォームを再送信しないように待機する必要があります。次のjQueryコードを使用してみました。
<script type="text/javascript">
$(document).ready(function() {
$("form#my_form").submit(function() {
$('input').attr('disabled', 'disabled');
$('a').attr('disabled', 'disabled');
return true;
});
});
</script>
Firefoxでこれを試みると、すべてが無効になりますが、フォームに含まれるPOSTデータのいずれも送信されません。複数の送信ボタンがあるため、ボタンをフォームとともに送信する必要があるため、jQueryを使用してフォームを送信することはできません。また、POSTにどの値が含まれているかを判断します。通常どおりフォームを送信する必要があり、その直後にすべてを無効にする必要があります。
ありがとう!
2018年の更新:この古い回答に対していくつかのポイントを得ただけで、best解決策は、重複した送信が無害になるように操作をべき等にすることです。
たとえば、フォームが注文を作成する場合、フォームに一意のIDを入力します。サーバーは、そのIDを持つ注文作成リクエストを初めて見ると、それを作成して「成功」と応答する必要があります。後続の送信も「成功」と応答する必要があります(クライアントが最初の応答を取得しなかった場合)が、何も変更しないでください。
競合状態を防ぐために、データベースの一意性チェックを介して重複を検出する必要があります。
あなたの問題はこの行だと思います:
$('input').attr('disabled','disabled');
フォームが送信するデータの入力を含むすべての入力を無効にしています。
送信ボタンのみを無効にするには、couldを行います:
$('button[type=submit], input[type=submit]').prop('disabled',true);
ただし、ボタンが無効になっている場合でも、IEがフォームを送信するとは思わない。別のアプローチをお勧めします。
次のコードでこの問題を解決しました。ここでのコツは、jQueryのdata()
を使用して、フォームが既に送信済みかどうかをマークすることです。そうすれば、IEアウトを驚かせる送信ボタンをいじる必要はありません。
// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
$(this).on('submit',function(e){
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
}
});
// Keep chainability
return this;
};
次のように使用します。
$('form').preventDoubleSubmission();
ページのロードごとにを複数回送信できるAJAXフォームがある場合は、それを示すクラスを与えることができます。次のように、セレクタからそれらを除外します。
$('form:not(.js-allow-double-submission)').preventDoubleSubmission();
タイミングのアプローチが間違っています-クライアントのブラウザでアクションがどのくらいかかるかをどのように知るのですか?
$('form').submit(function(){
$(this).find(':submit').attr('disabled','disabled');
});
フォームを送信すると、内部のすべての送信ボタンが無効になります。
Firefoxでボタンを無効にすると、履歴に戻るときにこの状態が記憶されます。それを防ぐには、たとえば、ページの読み込み時にボタンを有効にする必要があります。
ネイサン・ロングの答えは進むべき道だと思います。私にとっては、クライアント側の検証を使用しているため、フォームが有効であるという条件を追加しただけです。
EDIT:これが追加されていない場合、クライアント側の検証でエラーが発生した場合、ユーザーはフォームを送信できません。
// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function () {
$(this).on('submit', function (e) {
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
alert('Form already submitted. Please wait.');
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
// ADDED requirement that form be valid
if($form.valid()) {
$form.data('submitted', true);
}
}
});
// Keep chainability
return this;
};
event.timeStamp
はFirefoxでは機能しません。 falseを返すことは非標準です。event.preventDefault()
を呼び出す必要があります。そして、その間、 always制御構造と共にブレースを使用します 。
これまでの回答をすべてまとめると、仕事を行い、クロスブラウザーで動作するプラグインがあります。
jQuery.fn.preventDoubleSubmission = function() {
var last_clicked, time_since_clicked;
jQuery(this).bind('submit', function(event) {
if(last_clicked) {
time_since_clicked = jQuery.now() - last_clicked;
}
last_clicked = jQuery.now();
if(time_since_clicked < 2000) {
// Blocking form submit because it was too soon after the last submit.
event.preventDefault();
}
return true;
});
};
Kern3lに対処するために、送信ボタンのダブルクリックを停止しようとしているという理由だけで、タイミングメソッドが機能します。送信に対する応答時間が非常に長い場合は、送信ボタンまたはフォームをスピナーに置き換えることをお勧めします。
上記の例のほとんどがそうであるように、フォームの後続の送信を完全にブロックすることには、1つの悪い副作用があります。製。これは間違いなく怒っているユーザーになります。
jquery-safeform プラグインをチェックしてください。
使用例:
$('.safeform').safeform({
timeout: 5000, // disable next submission for 5 sec
submit: function() {
// You can put validation and ajax stuff here...
// When done no need to wait for timeout, re-enable the form ASAP
$(this).safeform('complete');
return false;
}
});
Nathan Longの approach を改善する可能性があります。すでに送信されたフォームを検出するためのロジックを次のフォームに置き換えることができます。
var lastTime = $(this).data("lastSubmitTime");
if (lastTime && typeof lastTime === "object") {
var now = new Date();
if ((now - lastTime) > 2000) // 2000ms
return true;
else
return false;
}
$(this).data("lastSubmitTime", new Date());
return true; // or do an ajax call or smth else
JQuery Validateプラグインを使用する場合は、既に送信ハンドラが実装されています。その場合、複数の実装ハンドラを実装する理由はありません。コード:
jQuery.validator.setDefaults({
submitHandler: function(form){
// Prevent double submit
if($(form).data('submitted')===true){
// Previously submitted - don't submit again
return false;
} else {
// Mark form as 'submitted' so that the next submit can be ignored
$(form).data('submitted', true);
return true;
}
}
});
} else {
- block内で簡単に展開して、入力を無効にしたり、ボタンを送信したりできます。
乾杯
...ただし、フォームは、含まれるはずのPOSTデータのいずれも送信されません。
正しい。無効化されたフォーム要素の名前/値はサーバーに送信されません。これらをreadonly elementsとして設定する必要があります。
また、そのようにアンカーを無効にすることはできません。 HREFを削除する(推奨されません)か、デフォルトの動作を防ぐ(より良い方法)必要があります。例:
<script type="text/javascript">
$(document).ready(function(){
$("form#my_form").submit(function(){
$('input').attr('readonly', true);
$('input[type=submit]').attr("disabled", "disabled");
$('a').unbind("click").click(function(e) {
e.preventDefault();
// or return false;
});
});
</script>
私は結局、この投稿のアイデアを使用して、AtZakoのバージョンと非常によく似たソリューションを考え出しました。
jQuery.fn.preventDoubleSubmission = function() {
var last_clicked, time_since_clicked;
$(this).bind('submit', function(event){
if(last_clicked)
time_since_clicked = event.timeStamp - last_clicked;
last_clicked = event.timeStamp;
if(time_since_clicked < 2000)
return false;
return true;
});
};
このような使用:
$('#my-form').preventDoubleSubmission();
ロックアウトがトリガーされると、ページを更新するまで再度送信できないため、何らかの種類のタイムアウトを含まず、送信またはフォーム要素を無効にするだけのソリューションが問題を引き起こすことがわかりました。これは、ajaxの処理を行うときに問題を引き起こします。
これはおそらく、それほど空想ではないので、少し見栄えがよくなります。
NathanのソリューションをBootstrap 3に少し変更しました。これにより、ロードボタンに送信テキストが設定されます。さらに、30秒後にタイムアウトし、フォームを再送信できます。
jQuery.fn.preventDoubleSubmission = function() {
$('input[type="submit"]').data('loading-text', 'Loading...');
$(this).on('submit',function(e){
var $form = $(this);
$('input[type="submit"]', $form).button('loading');
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
$form.setFormTimeout();
}
});
// Keep chainability
return this;
};
jQuery.fn.setFormTimeout = function() {
var $form = $(this);
setTimeout(function() {
$('input[type="submit"]', $form).button('reset');
alert('Form failed to submit within 30 seconds');
}, 30000);
};
AJAXを使用してフォームを投稿する場合、async: false
を設定すると、フォームがクリアされる前に追加の送信ができなくなります。
$("#form").submit(function(){
var one = $("#one").val();
var two = $("#two").val();
$.ajax({
type: "POST",
async: false, // <------ Will complete submit before allowing further action
url: "process.php",
data: "one="+one+"&two="+two+"&add=true",
success: function(result){
console.log(result);
// do something with result
},
error: function(){alert('Error!')}
});
return false;
}
});
ここに私がそれをする方法があります:
$(document).ready(function () {
$('.class_name').click(function () {
$(this).parent().append('<img src="data:image/gif;base64,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" />');
$(this).hide();
});
});
私は同様の問題を抱えており、私の解決策は次のとおりです。
クライアント側の検証がない場合は、ここに記載されているjquery one()メソッドを使用できます。
これにより、ハンドラーが呼び出された後に無効になります。
$("#mysavebuttonid").on("click", function () {
$('form').submit();
});
私がやっているようにクライアント側の検証をしている場合は、少しややこしいです。上記の例では、検証に失敗した後に再度送信することはできません。代わりにこのアプローチを試してください
$("#mysavebuttonid").on("click", function (event) {
$('form').submit();
if (boolFormPassedClientSideValidation) {
//form has passed client side validation and is going to be saved
//now disable this button from future presses
$(this).off(event);
}
});
2つの送信ボタンを使用します。
<input id="sub" name="sub" type="submit" value="OK, Save">
<input id="sub2" name="sub2" type="submit" value="Hidden Submit" style="display:none">
そしてjQuery:
$("#sub").click(function(){
$(this).val("Please wait..");
$(this).attr("disabled","disabled");
$("#sub2").click();
});
送信ボタンの変更:
<input id="submitButtonId" type="submit" value="Delete" />
通常のボタンの場合:
<input id="submitButtonId" type="button" value="Delete" />
次に、クリック機能を使用します。
$("#submitButtonId").click(function () {
$('#submitButtonId').prop('disabled', true);
$('#myForm').submit();
});
必要なときにボタンを再度有効にすることを忘れないでください:
$('#submitButtonId').prop('disabled', false);
ポインタイベントの古き良きCSSトリックを信じることはできません。まだ言及されていません。無効な属性を追加することで同じ問題が発生しましたが、これはポストバックしません。以下を試して、#SubmitButtonを送信ボタンのIDに置き換えます。
$(document).on('click', '#SubmitButton', function () {
$(this).css('pointer-events', 'none');
})
なぜこれだけではないのですか?これはフォームを送信するだけでなく、送信ボタンを無効にします。
$('#myForm').on('submit', function(e) {
var clickedSubmit = $(this).find('input[type=submit]:focus');
$(clickedSubmit).prop('disabled', true);
});
また、jQuery Validateを使用している場合、これらの2行をif ($('#myForm').valid())
の下に配置できます。
私の解決策:
// jQuery plugin to prevent double submission of forms
$.fn.preventDoubleSubmission = function () {
var $form = $(this);
$form.find('[type="submit"]').click(function () {
$(this).prop('disabled', true);
$form.submit();
});
// Keep chainability
return this;
};
これで2回目の送信を停止できます
$("form").submit(function() {
// submit more than once return false
$(this).submit(function() {
return false;
});
// submit once return true
return true; // or do what you want to do
});
});
送信時に単純なカウンターを使用します。
var submitCounter = 0;
function monitor() {
submitCounter++;
if (submitCounter < 2) {
console.log('Submitted. Attempt: ' + submitCounter);
return true;
}
console.log('Not Submitted. Attempt: ' + submitCounter);
return false;
}
そして、フォームを送信するときにmonitor()
関数を呼び出します。
<form action="/someAction.go" onsubmit="return monitor();" method="POST">
....
<input type="submit" value="Save Data">
</form>
私の場合、フォームのonsubmitには検証コードが含まれていたため、 Nathan Long onsubmitチェックポイントを含む回答を増やします
$.fn.preventDoubleSubmission = function() {
$(this).on('submit',function(e){
var $form = $(this);
//if the form has something in onsubmit
var submitCode = $form.attr('onsubmit');
if(submitCode != undefined && submitCode != ''){
var submitFunction = new Function (submitCode);
if(!submitFunction()){
event.preventDefault();
return false;
}
}
if ($form.data('submitted') === true) {
/*Previously submitted - don't submit again */
e.preventDefault();
} else {
/*Mark it so that the next submit can be ignored*/
$form.data('submitted', true);
}
});
/*Keep chainability*/
return this;
};
このコードは、ボタンラベルにロードを表示し、ボタンを
状態を無効にし、処理後、元のボタンテキストを再度有効にして戻します**
$(function () {
$(".btn-Loading").each(function (idx, Elm) {
$(Elm).click(function () {
//do processing
if ($(".input-validation-error").length > 0)
return;
$(this).attr("label", $(this).text()).text("loading ....");
$(this).delay(1000).animate({ disabled: true }, 1000, function () {
//original event call
$.when($(Elm).delay(1000).one("click")).done(function () {
$(this).animate({ disabled: false }, 1000, function () {
$(this).text($(this).attr("label"));
})
});
//processing finalized
});
});
});
// and fire it after definition
}
);