Domanda

Ho un form che richiede un po ' di tempo per il server di processo.Ho bisogno di assicurarsi che l'utente attende e non tenta di inviare nuovamente il modulo facendo clic sul pulsante nuovo.Ho provato con il seguente codice jQuery:

<script type="text/javascript">
$(document).ready(function() {
    $("form#my_form").submit(function() {
        $('input').attr('disabled', 'disabled');
        $('a').attr('disabled', 'disabled');
        return true;
    });
});
</script>

Quando provo questo in Firefox tutto viene disabilitato, ma il modulo non viene inviato con qualsiasi dei dati POST si dovrebbe includere.Non è possibile utilizzare jQuery per inviare il modulo, perché ho bisogno del pulsante per essere inviato con il modulo come ci sono più pulsanti di invio e determinare quale è stato utilizzato da quale valore è incluso nel POST.Ho bisogno di un modulo per essere presentata come è solito e ho bisogno di disattivare tutto il diritto dopo che succede.

Grazie!

È stato utile?

Soluzione

Aggiornamento nel 2018:Ho appena ricevuto alcuni punti per questa vecchia risposta e volevo solo aggiungere che the migliore la soluzione sarebbe rendere l'operazione idempotente in modo che gli invii duplicati siano innocui.

Ad esempio, se il modulo crea un ordine, inserisci un ID univoco nel modulo.La prima volta che il server vede una richiesta di creazione di un ordine con quell'ID, dovrebbe crearla e rispondere "successo".Anche gli invii successivi dovrebbero rispondere "successo" (nel caso in cui il cliente non abbia ricevuto la prima risposta) ma non dovrebbero cambiare nulla.

I duplicati dovrebbero essere rilevati tramite un controllo di unicità nel database per prevenire condizioni di competizione.


Penso che il tuo problema sia questa riga:

$('input').attr('disabled','disabled');

Stai disabilitando TUTTI gli input, inclusi, immagino, quelli i cui dati dovrebbe essere inviato dal modulo.

Per disabilitare solo i pulsanti di invio, tu Potevo Fai questo:

$('button[type=submit], input[type=submit]').prop('disabled',true);

Tuttavia, non penso che IE invierà il modulo anche se questi pulsanti sono disabilitati.Suggerirei un approccio diverso.

Un plugin jQuery per risolverlo

Abbiamo appena risolto questo problema con il seguente codice.Il trucco qui sta usando jQuery data() per contrassegnare il modulo come già inviato o meno.In questo modo non dobbiamo interferire con i pulsanti di invio, il che fa impazzire 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;
};

Usalo in questo modo:

$('form').preventDoubleSubmission();

Se ci sono moduli AJAX, questo Dovrebbe essere autorizzato a inviare più volte per caricamento della pagina, puoi assegnare loro una classe che lo indica, quindi escluderli dal tuo selettore in questo modo:

$('form:not(.js-allow-double-submission)').preventDoubleSubmission();

Altri suggerimenti

approccio tempismo è sbagliato -? Come fai a sapere quanto tempo l'azione avrà sul browser del client

Come fare

$('form').submit(function(){
  $(this).find(':submit').attr('disabled','disabled');
});

Al momento della presentazione forma che disabilita tutti i pulsanti presentare al suo interno.

Ricordate, in Firefox quando si disattiva un pulsante questo stato sarà ricordato quando si va indietro nella storia. Per evitare che si deve attivare pulsanti sul caricamento della pagina, per esempio.

Credo che la risposta di Nathan Long è la strada da percorrere. Per quanto mi riguarda, io sto usando la validazione lato client, quindi ho solo aggiunto una condizione che la forma sia valida.

Modifica :. Se questo non viene aggiunto, l'utente non sarà mai in grado di inviare il modulo, se la validazione lato client rileva un errore

        // 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 non funziona in Firefox. Tornando falsa è non standard, si dovrebbe chiamare event.preventDefault(). E già che ci siamo, sempre utilizzare parentesi con un controllo costrutto .

Per riassumere tutte le risposte precedenti, ecco un plugin che fa il lavoro e lavora cross-browser.

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;
    });
};

Per indirizzo Kern3l, le opere di metodo tempistica per me semplicemente perché stiamo cercando di fermare un doppio clic del pulsante di invio. Se si dispone di un tempo di risposta molto lungo per una sottomissione, vi consiglio di sostituire il pulsante o la forma presentare con uno spinner.

bloccando completamente le successive osservazioni della forma, come la maggior parte degli esempi di cui sopra, ha un cattivo effetto collaterale: se c'è un errore di rete e vogliono cercare di ripresentare, non sarebbero in grado di farlo e perderebbero la cambiamenti che hanno fatto. Questo sarebbe sicuramente fare un utente arrabbiato.

, controlla jquery-safeform plugin.

Esempio di utilizzo:

$('.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;
    }
});

...ma il modulo non viene inviato con uno dei POST i dati si suppone che includere.

Corretto.Disabili elemento del modulo di nomi/valori non saranno inviati al server.Si dovrebbe impostare il readonly elementi.

Inoltre, ancore non può essere disattivato come che.Sarà necessario rimuovere il loro Href (non raccomandato) o impedire il loro comportamento di default (meglio), ad esempio:

<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>

C'è la possibilità di migliorare l'approccio di Nathan Long . È possibile sostituire la logica per il rilevamento della forma già presentato con questo:

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

codice di Nathan, ma per jQuery plugin di convalida

Se vi capita di usare jQuery Convalida plug-in, che già hanno presentato gestore attuati, e in questo caso non v'è alcun motivo per implementare più di uno. Il codice:

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;
    }
  }
});

Si può facilmente espandere all'interno del } else { blocco agli ingressi disabilitare e / o pulsante di invio.

Saluti

Ho finito per usare le idee da questo post per trovare una soluzione che è molto simile alla versione di 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;
  });   
};

Utilizzando in questo modo:

$('#my-form').preventDoubleSubmission();

Ho trovato che le soluzioni che non includevano una sorta di timeout, ma di sottomissione o di elementi del modulo disabili causato problemi solo con disabilità perché una volta che viene attivato il lock-out non è possibile inviare di nuovo fino a quando si aggiorna la pagina. Questo fa sì che alcuni problemi per me quando si fa ajax roba.

Questo può probabilmente essere prettied un po 'come la sua non che la fantasia.

Se si utilizza AJAX per inviare un modulo, insieme async: false dovrebbe impedire sottomette aggiuntivi prima allontana la forma:

$("#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;
   }
});

Modificata la soluzione di Nathan un po 'per il Bootstrap 3. Questo creerà un testo carico al pulsante di invio. Inoltre ci si timeout dopo 30 secondi e permettere che il modulo essere ripresentata.

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);
};

L'utilizzo di due pulsanti presentare.

<input id="sub" name="sub" type="submit" value="OK, Save">
<input id="sub2" name="sub2" type="submit" value="Hidden Submit" style="display:none">

E jQuery:

$("#sub").click(function(){
  $(this).val("Please wait..");
  $(this).attr("disabled","disabled");
  $("#sub2").click();
});

Ho avuto problemi simili e la mia soluzione (s) sono i seguenti.

Se non si dispone di alcuna convalida lato client allora si può semplicemente utilizzare il metodo uno jQuery () come documentato qui.

http://api.jquery.com/one/

Disabilita il gestore dopo il suo stato invocato.

$("#mysavebuttonid").on("click", function () {
  $('form').submit();
});

Se stai facendo validazione lato client come stavo facendo allora il suo un po 'più complicato. L'esempio di cui sopra non avrebbe permesso di inviare di nuovo dopo la convalida non è riuscita. Prova questo approccio invece

$("#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);
   }
});

qui è come lo faccio:

$(document).ready(function () {
  $('.class_name').click(function () {
    $(this).parent().append('<img src="data:image/gif;base64,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" />');
    $(this).hide();
  });
});

crediti: https://github.com/phpawy/jquery-submit-once

Usa contatore semplice su inviare.

    var submitCounter = 0;
    function monitor() {
        submitCounter++;
        if (submitCounter < 2) {
            console.log('Submitted. Attempt: ' + submitCounter);
            return true;
        }
        console.log('Not Submitted. Attempt: ' + submitCounter);
        return false;
    }

E la funzione di chiamata in monitor() inviare il modulo.

    <form action="/someAction.go" onsubmit="return monitor();" method="POST">
        ....
        <input type="submit" value="Save Data">
    </form>

questo codice visualizzerà caricamento sulla etichetta del pulsante e pulsante di impostazione per

Stato di disable, quindi dopo l'elaborazione, riattivare e ritorno di nuovo il testo del pulsante originale **

$(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
}

);

La mia soluzione:

// 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;
};

Nel mio caso onsubmit del form avuto qualche codice di validazione, così ho incremento Nathan Long risposta tra cui un posto di blocco 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;
    };

Pulsante Modifica invio:

<input id="submitButtonId" type="submit" value="Delete" />

Con pulsante normale:

<input id="submitButtonId" type="button" value="Delete" />

Quindi utilizzare la funzione clic:

$("#submitButtonId").click(function () {
        $('#submitButtonId').prop('disabled', true);
        $('#myForm').submit();
    });

E ricorda di riattivare il pulsante quando è necessario:

$('#submitButtonId').prop('disabled', false);

Non riesco a credere che il buon vecchio stile css trick di puntatore-eventi: nessuno non è stato ancora citato. Ho avuto lo stesso problema con l'aggiunta di un attributo disabled ma questo non post indietro. Prova il seguito e sostituire #SubmitButton con l'ID del pulsante di invio.

$(document).on('click', '#SubmitButton', function () {
    $(this).css('pointer-events', 'none');
})

Perché non solo questo - questo dovrà presentare la forma, ma anche disabilitare il pulsante alla consegna,

   $('#myForm').on('submit', function(e) {
       var clickedSubmit = $(this).find('input[type=submit]:focus');
       $(clickedSubmit).prop('disabled', true);
   });

Inoltre, se si sta utilizzando jQuery convalida, si può mettere queste due righe sotto if ($('#myForm').valid()).

È possibile arrestare la seconda presentare da questo

$("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
    });
});

ho risolto un problema molto simile utilizzando:

$("#my_form").submit(function(){
    $('input[type=submit]').click(function(event){
        event.preventDefault();
    });
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top