防止双重提交的形式在jQuery
-
26-09-2019 - |
题
我有一种形式,花一点时间用于服务器的进程。我需要确保用户的等待和不试图重新提交的形式通过点击按钮。我试图用如下。:
<script type="text/javascript">
$(document).ready(function() {
$("form#my_form").submit(function() {
$('input').attr('disabled', 'disabled');
$('a').attr('disabled', 'disabled');
return true;
});
});
</script>
当我试试这个在火狐的一切被禁用但形式不提出任何员额数据也应该包括的内容。我不能使用jQuery的提交形式,因为我需要按钮将提交的形式有多种提交的按钮我确定这是用哪一个是价值被包括在该员额。我需要的形式提交,因为它通常是和我需要禁止一切权利之后发生的。
谢谢!
解决方案
更新于2018年:我刚得到一些分,这个古老的答案,只是想补充一点,在最佳的解决方案是使操作幂等,这样重复提交是无害的。
例如,如果表单创建订单,把一个唯一的ID的格式。第一次服务器看到一个订单创建请求与ID,它应该创建它,并响应“成功”。随后意见书也应该响应“成功”(如果客户没有拿到第一反应),但不应该改变任何东西。
重复应通过在数据库中,以防止竞争条件唯一性检查来检测。
我觉得你的问题是这一行:
$('input').attr('disabled','disabled');
您将禁止所有的投入,包括,我猜,其数据的形式被认为的那些提交。
要仅禁用提交按钮(S),你的可以做到这一点:
$('button[type=submit], input[type=submit]').prop('disabled',true);
不过,我不认为IE浏览器将提交表单如果连这些按钮将被禁用。我建议一个不同的方法。
甲jQuery插件来解决它
我们刚刚解决了这个问题,下面的代码。这里的技巧是使用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中,当您禁用按钮,这种状态将被记住,当你回顾历史。为了防止这种情况必须启用在页面加载按钮,例如
我觉得森龙的回答是要走的路。对我来说,我使用的客户端验证,所以我只是增加了一个条件,即形式是有效的。
修改强>:如果不添加时,用户将永远无法提交表单,如果客户端验证遇到错误
// 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()
。虽然我们在这,的总是的使用大括号与对照构建。
要总结以前所有的答案,这里是一个插件,没有工作和工作的跨浏览器。
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,时序方法对我的作品只是因为我们正在试图阻止的双击提交按钮。如果你有一个很长的响应时间提交,我建议您更换提交按钮或形式有微调。
完全阻止形式的后续提交,因为大多数的上面的例子做,有一个不好的副作用:如果出现网络故障,他们想尝试重新提交,他们将无法这样做,将失去更改他们做了。这肯定会使愤怒的用户。
请,检查出的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;
}
});
...但形式不提交 任员额数据也是应该 包括。
正确的。无障碍形成元素名称/价值观不会被送到服务器。你应该将它们作为 只读的 元素。
此外,锚不能无障碍的那样。你将需要删除他们的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>
有是提高内森龙的方法可能性一>。 可以用这一个替换的逻辑检测已经提交形式:
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
Nathan的代码,但对于jQuery验证插件
如果你碰巧使用jQuery验证插件,他们已经有提交处理程序来实现,在这种情况下,没有理由实施不止一个。的代码:
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 {
块内展开它禁止输入和/或提交按钮。
干杯
我结束了使用从这篇文章的想法拿出一个解决方案,这是非常相似的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的东西时,引起了我的一些问题。
这可能可以美化了一番一点作为其不是花式。
如果使用的 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;
}
});
修改Nathan的解决方案,引导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);
};
使用两个提交按钮。
<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();
});
我已经遇到类似问题,我的溶液(S)如下:
如果您没有任何客户端验证则可以简单地使用的jquery一个()方法,作为记录在这里。
其被调用这将禁用处理程序之后。
$("#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);
}
});
下面是我如何做到这一点:
$(document).ready(function () {
$('.class_name').click(function () {
$(this).parent().append('<img src="data:image/gif;base64,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" />');
$(this).hide();
});
});
使用简单的计数器。
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>
这个代码将显示按钮标签上装载,和SET按钮
禁用状态,那么处理之后,重新启用,并返回原来的按钮文本**
$(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
}
);
我的解决办法:
// 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;
};
在我的情况下,表单的onsubmit有一些验证代码,所以我增加森龙答案包括的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;
};
更改提交按钮:
<input id="submitButtonId" type="submit" value="Delete" />
使用普通按钮:
<input id="submitButtonId" type="button" value="Delete" />
然后使用点击功能:
$("#submitButtonId").click(function () {
$('#submitButtonId').prop('disabled', true);
$('#myForm').submit();
});
和记住的是necesary时重新启用按钮:
$('#submitButtonId').prop('disabled', false);
我不能相信的指针事件的良好的老式CSS技巧:无尚未提及。我加入了禁用的属性有同样的问题,但是这并没有张贴回来。尝试下面并与您提交按钮的ID替换#SubmitButton。
$(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验证,就可以把这两行下if ($('#myForm').valid())
。
可以停止通过该
的第二提交$("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
});
});
我使用解决了一个非常类似的问题:
$("#my_form").submit(function(){
$('input[type=submit]').click(function(event){
event.preventDefault();
});
});