Come posso ottenere il pulsante che ha causato l'invio dall'evento di invio del modulo?


110

Sto cercando di trovare il valore del pulsante di invio che ha attivato l'invio del modulo

$("form").submit(function() {

});

Potrei eventualmente attivare un evento $ ("input [type = submit]"). Click () per ogni pulsante e impostare qualche variabile, ma sembra meno elegante di come togliere il pulsante dal modulo durante l'invio.


2
Nota che non esiste necessariamente alcun pulsante di questo tipo. Uno script potrebbe andare bene formobj.submit(). Penso che gli eventi di clic siano la strada da percorrere.
Jason Orendorff

1
Per i browser moderni c'è ora event.submitterche ti dà il <button>o <input type="submit">che è stato cliccato.
gfv

Risposte:


107

Ho sfruttato document.activeElementcome abbozzato in questa risposta: come ottenere l'elemento focalizzato con jQuery?

$form.on('submit', function() {
    var $btn = $(document.activeElement);

    if (
        /* there is an activeElement at all */
        $btn.length &&

        /* it's a child of the form */ 
        $form.has($btn) &&

        /* it's really a submit element */
        $btn.is('button[type="submit"], input[type="submit"], input[type="image"]') &&

        /* it has a "name" attribute */
        $btn.is('[name]')
    ) {
        console.log("Seems, that this element was clicked:", $btn);
        /* access $btn.attr("name") and $btn.val() for data */
    }
});

Approfitto del fatto che il pulsante è sempre l'elemento focalizzato dopo averlo cliccato. Questo non funzionerà, se esegui una operazione blur()subito dopo il clic.

@Doin ha individuato un altro inconveniente. Se un utente invia il modulo tramite enterin un campo di testo, il document.activeElementnon è impostato. Dovresti fare attenzione a questo da solo, gestendo keypresseventi in input[type="text"]e simili.

Aggiornamento 2017-01: per la mia libreria Hyperform ho scelto di non utilizzare activeElementma di catturare tutti gli eventi che portano all'invio del modulo. Il codice per questo è su Github.

Se ti capita di utilizzare Hyperform, ecco come accederai al pulsante che ha attivato l'invio:

$(form).on('submit', function(event) {
  var button = event.submittedVia;
});

1
MDN dice di sì. (FF3, IE4, Chrome 2, Safari 4, Opera 9)
Boldewyn

1
Questa dovrebbe essere la risposta.
Royi Namir

2
Hmmm ... funziona se il modulo viene compilato tramite [Invio]? Spec dice che dovrebbe essere equivalente a fare clic sul pulsante di invio predefinito, ma non sono sicuro che lo lasci come elemento attivo o meno.
Doin

8
Purtroppo, non puoi fare affidamento solo suactiveElement , perché il "mittente" può essere definito: A. Tramite autentico clic di attivazione (cliccato direttamente con il mouse o la tastiera Spazio / Invio); B. Tramite attivazione del clic sintetico ( buttonElement.click()o buttonElement.dispatch(new MouseEvent(...)), senza mettere a fuoco); C. tramite sottomissione implicita del modulo (interazione della tastiera con il campo di un altro modulo) D. a nessuno, quandoformElement.submit()
mems

5
Solo una nota per mantenere le cose attuali. A partire da ora, Safari imposta activeElement sul corpo del documento quando si fa clic su un pulsante di invio. Mi sono imbattuto in questo problema su Safari 9.1
coderkevin

35

Ho implementato questo e suppongo che funzionerà.

$(document).ready(function() {
    $("form").submit(function() { 

    var val = $("input[type=submit][clicked=true]").val()

    // DO WORK

});

e questo è l'evento del pulsante di invio che lo imposta

$("form input[type=submit]").click(function() {
    $("input[type=submit]", $(this).parents("form")).removeAttr("clicked");
    $(this).attr("clicked", "true");
});

Grazie per le risposte, ma questo non è terribilmente inelegante ...


1
Non compatibile con crossbrowser / più pulsanti di invio.
user1610743

2
È garantito che l'evento clic venga attivato prima dell'evento di invio del modulo? Suggerirei di dare al form una doNotSubmitclasse, all'interno della funzione di invio controllare se la classe non è esistente (altrimenti non inviare), all'interno dell'evento click rimuovere la classe del form doNotSubmite fare un $ (''. MyForm '). Trigger ('Invia'); dopo aver aggiunto il valore del pulsante di invio come campo nascosto
Hafenkranich

2
@Hafenkranich In alcune rare occasioni su Chrome l'evento clic viene attivato DOPO l'evento di invio.
romanoza

@roamnoza è esattamente quello che ho incontrato anch'io.
Hafenkranich

2
@ j4k3 Hai una soluzione migliore? Questa risposta è di 8 anni
cacciatore

10

Ho creato un modulo di prova e utilizzando Firebug ho trovato questo modo per ottenere il valore;

$('form').submit(function(event){
  alert(event.originalEvent.explicitOriginalTarget.value);
}); 

Sfortunatamente, solo Firefox supporta questo evento.


5
IE non ha questa proprietà (explicitOriginalTarget)
andres descalzo

1
Il buon vecchio IE che ha rovinato tutto, è passato attraverso Firebug e non è riuscito a vedere nessun altro valore di oggetto da usare, ma si è semplicemente dimenticato dei browser alternativi. Non sorpreso di sentire che non lo fa, però, dovrà controllare Chrome.
Dave Anderson

11
Solo Firefox supporta questo evento.
Andy E

Quindi, fondamentalmente, c'è qualcosa in HTML che non può essere fatto in JS ... Mozilla ha deciso di implementare la funzionalità mancante e nessuno ha seguito l'esempio? Questo è il motivo per cui non possiamo avere cose belle
aross

6

Ecco un approccio che sembra più pulito per i miei scopi.

Primo, per tutte le forme:

$('form').click(function(event) {
  $(this).data('clicked',$(event.target))
});

Quando questo evento clic viene generato per un modulo, registra semplicemente la destinazione di origine (disponibile nell'oggetto evento) a cui accedere in seguito. Questo è un tratto piuttosto ampio, in quanto verrà attivato per qualsiasi clic in qualsiasi punto del modulo. I commenti di ottimizzazione sono ben accetti, ma sospetto che non causeranno mai problemi evidenti.

Quindi, in $ ('form'). Submit (), puoi chiedere cosa è stato cliccato l'ultima volta, con qualcosa di simile

if ($(this).data('clicked').is('[name=no_ajax]')) xhr.abort();

6

Ora c'è una submitterproprietà standard nell'evento submit.
Già implementato in Firefox 75 !

document.addEventListener('submit',function(e){
    console.log(e.submitter)
})

Per i browser che non lo supportano, utilizza questo polyfill :

!function(){
    var lastBtn = null
    document.addEventListener('click',function(e){
        if (!e.target.closest) return;
        lastBtn = e.target.closest('button, input[type=submit]');
    }, true);
    document.addEventListener('submit',function(e){
        if ('submitter' in e) return;
        var canditates = [document.activeElement, lastBtn];
        for (var i=0; i < canditates.length; i++) {
            var candidate = canditates[i];
            if (!candidate) continue;
            if (!candidate.form) continue;
            if (!candidate.matches('button, input[type=button], input[type=image]')) continue;
            e.submitter = candidate;
            return;
        }
        e.submitter = e.target.querySelector('button, input[type=button], input[type=image]')
    }, true);
}();

4

Secondo questo collegamento , l'oggetto Event contiene un campo Event.target, che:

Restituisce una stringa che rappresenta l'oggetto che ha avviato l'evento.

Ho appena creato una pagina per testare qual è quel valore e sembra che quella rappresentazione sia per il modulo stesso, non per il pulsante su cui si è fatto clic. In altre parole, Javascript non fornisce la funzione per determinare il pulsante cliccato.

Per quanto riguarda la soluzione di Dave Anderson , potrebbe essere una buona idea testarla in più browser prima di utilizzarla. È possibile che funzioni bene, ma non posso dire in alcun modo.


1
Il targetrestituisce l'intero modulo. Quindi sfortunatamente non è utile rilevare il pulsante di invio corretto.
Hafenkranich

Lo dico nella mia risposta, @Hafenkranich.
cmptrgeekken

Event.targetnon è una stringa. È un EventTargetoggetto, che in questo caso è il modulo inviato stesso.
Akseli

4

Un approccio pulito consiste nell'utilizzare l'evento clic su ciascun pulsante del modulo. Di seguito è riportato un modulo html con i pulsanti Salva, Annulla ed Elimina:

<form  name="formname" action="/location/form_action" method="POST">
<input name="note_id" value="some value"/>
<input class="savenote" type="submit" value="Save"/>
<input class="cancelnote" type="submit" value="Cancel"/>
<input class="deletenote" type="submit" value="Delete" />
</form> 

Di seguito è riportato il jquery. Invio l '"azione" appropriata alla stessa funzione del server a seconda del pulsante selezionato ("salva" o "elimina"). Se si fa clic su "Annulla", ricarico la pagina.

$('.savenote').click(function(){
   var options = {
       data: {'action':'save'}
   };
   $(this).parent().ajaxSubmit(options);
   });


$('.deletenote').click(function(){
   var options = {
       data: {'action':'delete'}
   };
   $(this).parent().ajaxSubmit(options);
   });


$('.cancelnote').click(function(){
   window.location.reload(true);
   return false;
   });

3

Ho cercato e trovato diversi modi per ottenere il pulsante di invio name+ valueinviato al server utilizzando jQuery + AJAX. Non mi piacevano molto ...

Uno dei migliori è stata la soluzione del cacciatore presentata qui!

Ma ne ho scritto un altro io stesso.

Voglio condividere, perché è buono e, come avevo bisogno, funziona anche con i moduli caricati tramite ajax (dopo document.ready):

$(document).on('click', 'form input[type=submit]', function(){
    $('<input type="hidden" />').appendTo($(this).parents('form').first()).attr('name', $(this).attr('name')).attr('value', $(this).attr('value'));
});

Semplice! Quando si fa clic sul pulsante di invio, un campo nascosto viene aggiunto al modulo, utilizzando lo stesso namee valuedel pulsante di invio.

EDIT: la versione seguente è più facile da leggere. Inoltre, si occupa di rimuovere i campi nascosti precedentemente aggiunti (nel caso di inviare lo stesso modulo due volte, il che è perfettamente possibile quando si utilizza AJAX).

Codice migliorato:

$(document).on('click', 'form input[type=submit]', function(){
    var name   = $(this).attr('name');
    if (typeof name == 'undefined') return;
    var value  = $(this).attr('value');
    var $form  = $(this).parents('form').first();
    var $input = $('<input type="hidden" class="temp-hidden" />').attr('name', name).attr('value', value);
    $form.find('input.temp-hidden').remove();
    $form.append($input);
});

1+ Questo lo ha fatto per me. Grazie!
Lennart Rolland

Sembra che questo dipenda dal fatto che tutti <button/>condividono lo stesso nameattributo. Vorrei usare una classe e fare riferimento a quella nel tuo .remove().
binki

@binki: no, non è così. Ad ogni modo, ogni sviluppatore può adattare la soluzione alle proprie esigenze.
J. Bruni

jsfiddle.net/binki/d8ecv mostra cosa intendo per l' nameattributo. Se il modulo viene riutilizzato e contiene input di invio con nomi diversi, i vecchi input possono ingombrare il modulo.
binki

Ora vedo ... aggiornerò la mia risposta. (In effetti, non ho prestato molta attenzione al tuo commento a causa del fatto estraneo che hai menzionato l' <button/>elemento, mentre <input type="submit" />è usato nel codice ...)
J. Bruni

2

Ho provato alcuni degli esempi forniti, ma non hanno funzionato per i nostri scopi.

Ecco un violino da mostrare: http://jsfiddle.net/7a8qhofo/1/

Ho dovuto affrontare un problema simile ed è così che abbiamo risolto il problema nei nostri moduli.

$(document).ready(function(){

    // Set a variable, we will fill later.
    var value = null;

    // On submit click, set the value
    $('input[type="submit"]').click(function(){
        value = $(this).val();
    });

    // On data-type submit click, set the value
    $('input[type="submit"][data-type]').click(function(){
        value = $(this).data('type');
    });

    // Use the set value in the submit function
    $('form').submit(function (event){
        event.preventDefault();
        alert(value);
        // do whatever you need to with the content
    });
});

2

(evento)

function submForm(form,event){
             var submitButton;

             if(typeof event.explicitOriginalTarget != 'undefined'){  //
                 submitButton = event.explicitOriginalTarget;
             }else if(typeof document.activeElement.value != 'undefined'){  // IE
                 submitButton = document.activeElement;
             };

             alert(submitButton.name+' = '+submitButton.value)
}


<form action="" method="post" onSubmit="submForm(this, event); return false;">

1

puoi provare in questo modo con "event.originalEvent.x" e "event.originalEvent.y":

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
    <title>test</title>
</head>
<body>

    <form id="is_a_form">
        <input id="is_a_input_1" type="submit"><br />
        <input id="is_a_input_2" type="submit"><br />
        <input id="is_a_input_3" type="submit"><br />
        <input id="is_a_input_4" type="submit"><br />
        <input id="is_a_input_5" type="submit"><br />
    </form>

</body>
</html>
<script>
$(function(){

    $.fn.extend({
      inPosition: function(x, y) {

        return this.each(function() {

            try{
                var offset = $(this).offset();

                if ( (x >= offset.left) &&
                     (x <= (offset.left+$(this).width())) &&
                     (y >= offset.top) &&
                     (y <= (offset.top+$(this).height())) )
                {
                    $(this).css("background-color", "red");
                }
                else
                {
                        $(this).css("background-color", "#d4d0c8");
                }
                }
                catch(ex)
                {
                }

        });
      }
    }); 

    $("form").submit(function(ev) {

        $("input[type='submit']").inPosition(ev.originalEvent.x ,ev.originalEvent.y);
        return false;

    });

});
</script>

"accidenti" ?, funziona, non funziona, è utile, non utile, ...? , Non parlo un buon inglese
andres descalzo

@hunter come faccio a votare più volte il tuo commento?
Tom Auger

0

jQuery non sembra fornire quei dati sull'evento di invio. Sembra che il metodo che hai proposto sia la soluzione migliore.


0

Solo un'altra soluzione poiché nessun altro ha soddisfatto le mie esigenze. Il vantaggio è che vengono rilevati clic e pressione dei tasti (invio e spazio) .

// Detects the Events
var $form = $('form');
$form.on('click keypress', 'button[type="submit"]', function (ev) {

    // Get the key (enter, space or mouse) which was pressed.
    if (ev.which === 13 || ev.which === 32 || ev.type === 'click') {

        // Get the clicked button
        var caller = ev.currentTarget;

        // Input Validation
        if (!($form.valid())) {
            return;
        }

        // Do whatever you want, e.g. ajax...
        ev.preventDefault();
        $.ajax({
            // ...
        })
    }
}

Questo ha funzionato meglio per me.


0

Con un gestore di eventi più specifico e JQuery, il tuo oggetto evento è il pulsante su cui si fa clic. È inoltre possibile ottenere il modulo di delega da questo evento, se necessario.

$('form').on('click', 'button', function (e) {
  e.preventDefault();
  var
    $button = $(e.target),
    $form = $(e.delegateTarget);
  var buttonValue = $button.val();
});

Questo documento ha tutto il necessario per iniziare. JQuery Doc .


0

Scrivo questa funzione che mi aiuta

var PupulateFormData= function (elem) {
    var arr = {};
    $(elem).find("input[name],select[name],button[name]:focus,input[type='submit']:focus").each(function () {
        arr[$(this).attr("name")] = $(this).val();
    });
    return arr;

};

e poi Usa

var data= PupulateFormData($("form"));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.