جافاسكريبت - منع الإرسال المزدوج للنماذج في jQuery
لدي نموذج يستغرق بعض الوقت لمعالجته من قبل الخادم. أحتاج إلى التأكد من أن المستخدم ينتظر ولا يحاول إعادة إرسال النموذج من خلال النقر على الزر مرة أخرى. حاولت استخدام كود jQuery التالي:
<script type="text/javascript">
$(document).ready(function() {
$("form#my_form").submit(function() {
$('input').attr('disabled', 'disabled');
$('a').attr('disabled', 'disabled');
return true;
});
});
</script>
عندما أجرب هذا في فايرفوكس يتم تعطيل كل شيء ولكن النموذج لا يتم إرساله مع أي من بيانات POST المفترض تضمينها. لا أستطيع استخدام jQuery لإرسال النموذج لأنني أحتاج إلى أن يتم إرسال الزر مع النموذج حيث يوجد عدة أزرار إرسال وأحدد أيها تم استخدامه بناءً على القيمة المضمنة في POST. أحتاج أن يتم إرسال النموذج كما هو عادة وأحتاج إلى تعطيل كل شيء مباشرة بعد حدوث ذلك.
شكراً!
الإجابة رقم 1
تحديث في 2018: لقد حصلت للتو على بعض النقاط لهذا الجواب القديم، وأردت فقط أن أضيف أن أفضل حل سيكون جعل العملية قابلة للتكرار بدون تأثير بحيث تكون الإرسالات المكررة غير ضارة.
على سبيل المثال، إذا كان النموذج ينشئ طلبًا، ضع معرفًا فريدًا في النموذج. في المرة الأولى التي يرى فيها الخادم طلب إنشاء طلب بهذا المعرف، يجب أن ينشئه ويرد بـ "نجاح". يجب أن ترد الإرسالات التالية أيضًا بـ "نجاح" (في حال لم يحصل العميل على الرد الأول) ولكن لا ينبغي أن تغير أي شيء.
يجب اكتشاف النسخ المكررة عن طريق فحص التفرد في قاعدة البيانات لمنع ظروف التنافس.
أعتقد أن مشكلتك هي هذا السطر:
$('input').attr('disabled','disabled');
أنت تقوم بتعطيل جميع المدخلات، بما في ذلك، على ما أظن، تلك التي من المفترض أن يرسل النموذج بياناتها.
لتعطيل زر (أزرار) الإرسال فقط، يمكنك أن تفعل هذا:
$('button[type=submit], input[type=submit]').prop('disabled',true);
ومع ذلك، لا أعتقد أن إنترنت إكسبلورر سيقوم بإرسال النموذج حتى إذا كانت تلك الأزرار معطلة. أقترح اتباع نهج مختلف.
إضافة jQuery لحلها
لقد حللنا هذه المشكلة للتو باستخدام الكود التالي. الخدعة هنا هي استخدام data() في jQuery لتعليم النموذج على أنه تم إرساله بالفعل أم لا. بهذه الطريقة، لا نضطر إلى العبث بأزرار الإرسال، التي تسبب مشاكل في 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();
الإجابة رقم 2
نهج التوقيت خاطئ - كيف تعرف كم من الوقت ستستغرق العملية على متصفح العميل؟
كيف تفعل ذلك
$('form').submit(function(){
$(this).find(':submit').attr('disabled','disabled');
});
عند إرسال النموذج، سيقوم بإلغاء تفعيل جميع أزرار الإرسال بداخله.
تذكر، في فايرفوكس عندما تقوم بتعطيل زر سيتم تذكر هذه الحالة عند العودة في السجل. لمنع ذلك، عليك تمكين الأزرار عند تحميل الصفحة، على سبيل المثال.
الإجابة رقم 3
أعتقد أن إجابة ناثان لونغ هي الطريق الذي يجب اتباعه. بالنسبة لي، أنا أستخدم التحقق من صحة البيانات على جانب العميل، لذلك قمت فقط بإضافة شرط أن يكون النموذج صالحًا.
تحرير: إذا لم تتم إضافة هذا، فلن يكون المستخدم قادرًا أبدًا على تقديم النموذج إذا واجهت التحقق من الصحة على جانب العميل خطأ.
// 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;
};
الإجابة رقم 4
event.timeStamp لا يعمل في فايرفوكس. إرجاع القيمة 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، تعمل طريقة التوقيت بالنسبة لي ببساطة لأننا نحاول منع النقر المزدوج على زر الإرسال. إذا كان لديك وقت استجابة طويل جدًا للإرسال، أوصي باستبدال زر الإرسال أو النموذج بعجلة تحميل.
منع الإرسال اللاحق للنموذج تمامًا، كما تفعل معظم الأمثلة أعلاه، له تأثير جانبي سيء واحد: إذا كان هناك فشل في الشبكة وأرادوا محاولة إعادة الإرسال، فلن يكون بمقدورهم القيام بذلك وسيخسرون التغييرات التي قاموا بها. هذا بالتأكيد سيجعل المستخدم غاضبًا.
