Wie kann ich die Schaltfläche, die die Übermittlung verursacht hat, aus dem Formularübermittlungsereignis abrufen?

109

Ich versuche, den Wert der Schaltfläche "Senden" zu ermitteln, die das Senden des Formulars ausgelöst hat

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

});

Ich könnte möglicherweise ein $ ("input [type = submit]"). Click () -Ereignis für jede Schaltfläche auslösen und eine Variable festlegen, aber das scheint weniger elegant zu sein als das Ziehen der Schaltfläche aus dem Formular beim Senden.

Jäger
quelle
2
Beachten Sie, dass es nicht unbedingt eine solche Schaltfläche gibt. Ein Skript könnte reichen formobj.submit(). Ich denke, Klickereignisse sind der richtige Weg.
Jason Orendorff
1
Für moderne Browser gibt es jetzt das, event.submitterworauf Sie klicken <button>oder <input type="submit">was angeklickt wurde.
gfv

Antworten:

107

Ich habe document.activeElementwie in dieser Antwort skizziert genutzt: Wie erhalte ich das fokussierte Element mit 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 */
    }
});

Ich nutze die Tatsache, dass die Schaltfläche nach dem Klicken immer das fokussierte Element ist. Dies funktioniert nicht , wenn Sie blur()direkt nach dem Klicken ein ausführen.

@Doin hat einen weiteren Nachteil entdeckt. Wenn ein Benutzer das Formular über enterin einem Textfeld sendet, document.activeElementist das nicht festgelegt. Sie müssten selbst darauf achten, indem Sie keypressEreignisse in input[type="text"]und ähnlichem behandeln.

Update 2017-01: Für meine Bibliothek Hyperform habe ich mich dafür entschieden, nicht activeElementalle Ereignisse zu verwenden, sondern diese abzufangen, die zur Übermittlung des Formulars führen. Der Code dafür ist auf Github.

Wenn Sie Hyperform verwenden, können Sie auf folgende Weise auf die Schaltfläche zugreifen, die das Senden ausgelöst hat:

$(form).on('submit', function(event) {
  var button = event.submittedVia;
});
Boldewyn
quelle
1
MDN sagt ja. (FF3, IE4, Chrome 2, Safari 4, Opera 9)
Boldewyn
1
Dies sollte die Antwort sein.
Royi Namir
2
Hmmm ... funktioniert das, wenn das Formular über [Enter] gesendet wird? Laut Spezifikation sollte dies dem Klicken auf die Standard-Senden-Schaltfläche entsprechen, aber ich bin nicht sicher, ob sie als aktives Element verbleibt oder nicht.
Doin
8
Leider können Sie sich nicht nur darauf verlassenactiveElement , da der "Übermittler" definiert werden kann: A. Durch authentische Klickaktivierung (direkt mit der Maus oder der Tastatur geklickt Leertaste / Eingabetaste); B. Durch synthetische Klickaktivierung ( buttonElement.click()oder buttonElement.dispatch(new MouseEvent(...))ohne den Fokus zu verändern); C. über Formular implizite Übermittlung (Tastaturinteraktion mit dem Feld eines anderen Formulars) D. zu keiner, wennformElement.submit()
mems
5
Nur eine Notiz, um die Dinge auf dem neuesten Stand zu halten. Ab sofort setzt Safari activeElement auf den Dokumententext, wenn Sie auf eine Senden-Schaltfläche klicken. Ich bin auf Safari 9.1
Coderkevin
35

Ich habe dies implementiert und ich nehme an, es wird reichen.

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

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

    // DO WORK

});

und dies ist das Submit-Button-Ereignis, das es einrichtet

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

Vielen Dank für die Antworten, aber das ist nicht besonders unelegant ...

Jäger
quelle
1
Nicht Crossbrowser- / Multiple-Submit-Buttons-fähig.
user1610743
2
Ist garantiert, dass das Klickereignis vor dem Formularübermittlungsereignis ausgelöst wird? Ich würde vorschlagen, dem Formular eine doNotSubmitKlasse zu geben , innerhalb der Funktion doNotSubmit"Senden" zu prüfen, ob die Klasse nicht vorhanden ist (andernfalls nicht senden), innerhalb des Klickereignisses die Formularklasse zu entfernen und einen $ (''. MyForm '). Trigger auszuführen ('einreichen'); nach dem Hinzufügen des Submit-Button-Werts als verstecktes Feld
Hafenkranich
2
@Hafenkranich In einigen seltenen Fällen wird das Klickereignis in Chrome NACH dem Übermittlungsereignis ausgelöst.
Romanoza
@roamnoza genau das habe ich auch erlebt.
Hafenkranich
2
@ j4k3 Hast du eine bessere Lösung? Diese Antwort ist 8 Jahre alt
Jäger
10

Ich habe ein Testformular erstellt und mithilfe von Firebug diesen Weg gefunden, um den Wert zu erhalten.

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

Leider unterstützt nur Firefox dieses Ereignis.

Dave Anderson
quelle
5
IE hat diese Eigenschaft nicht (explizitOriginalTarget)
andres descalzo
1
Der gute alte IE hat es vermasselt, Firebug durchlaufen und konnte keine anderen zu verwendenden Objektwerte sehen, vergaß aber einfach alternative Browser. Nicht überrascht zu hören, dass dies nicht der Fall ist, muss Chrome überprüfen.
Dave Anderson
11
Nur Firefox unterstützt dieses Ereignis.
Andy E
Grundsätzlich gibt es in HTML etwas, das in JS nicht möglich ist ... Mozilla hat beschlossen, die fehlende Funktion zu implementieren, und niemand ist diesem Beispiel gefolgt? Deshalb können wir keine schönen Dinge haben
über den
6

Hier ist ein Ansatz, der für meine Zwecke sauberer erscheint.

Erstens für alle Formen:

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

Wenn dieses Klickereignis für ein Formular ausgelöst wird, zeichnet es einfach das Ursprungsziel (im Ereignisobjekt verfügbar) auf, auf das später zugegriffen werden soll. Dies ist ein ziemlich breiter Strich, da er für jeden Klick irgendwo auf dem Formular ausgelöst wird. Optimierungskommentare sind willkommen, aber ich vermute, dass sie niemals erkennbare Probleme verursachen werden.

Dann können Sie in $ ('form'). Submit () mit so etwas wie abfragen, was zuletzt angeklickt wurde

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

submitterDas Submit-Ereignis enthält jetzt eine Standardeigenschaft .
Bereits in Firefox implementiert!

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

Verwenden Sie für Browser, die dies nicht unterstützen, diese Polyfüllung :

!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);
}();
Tobias Buschor
quelle
4

Gemäß diesem Link enthält das Ereignisobjekt ein Feld Event.target, das:

Gibt eine Zeichenfolge zurück, die das Objekt darstellt, das das Ereignis ausgelöst hat.

Ich habe gerade eine Seite erstellt, auf der getestet wird, was dieser Wert ist, und es sieht so aus, als ob diese Darstellung für das Formular selbst und nicht für die angeklickte Schaltfläche gilt. Mit anderen Worten, Javascript bietet nicht die Möglichkeit, die angeklickte Schaltfläche zu bestimmen.

In Bezug auf die Lösung von Dave Anderson ist es möglicherweise eine gute Idee, dies in mehreren Browsern zu testen, bevor Sie es verwenden. Es ist möglich, dass es gut funktioniert, aber ich kann es nicht so oder so sagen.

cmptrgeekken
quelle
1
Das targetgibt das gesamte Formular zurück. Daher ist es leider nicht hilfreich, den richtigen Submit-Button zu erkennen.
Hafenkranich
Das sage ich auch in meiner Antwort: @Hafenkranich.
cmptrgeekken
Event.targetist keine Zeichenfolge. Es ist ein EventTargetObjekt, in diesem Fall das übermittelte Formular selbst.
Akseli
4

Ein sauberer Ansatz besteht darin, das Klickereignis für jede Formularschaltfläche zu verwenden. Es folgt ein HTML-Formular mit Schaltflächen zum Speichern, Abbrechen und Löschen:

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

Es folgt die Abfrage. Ich sende die entsprechende 'Aktion' an dieselbe Serverfunktion, je nachdem, auf welche Schaltfläche geklickt wurde ('Speichern' oder 'Löschen'). Wenn auf "Abbrechen" geklickt wird, lade ich die Seite einfach neu.

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

Ich suchte und fand verschiedene Möglichkeiten, um die Senden- Schaltfläche name+ valuemit jQuery + AJAX an den Server zu senden. Ich mochte sie nicht sehr ...

Eines der besten war die hier vorgestellte Jägerlösung!

Aber ich habe selbst einen anderen geschrieben.

Ich möchte teilen, weil es gut ist und bei Bedarf auch mit Formularen funktioniert, die über Ajax geladen wurden (nach 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'));
});

Einfach! Wenn Sie auf die Schaltfläche "Senden" klicken, wird dem Formular ein ausgeblendetes Feld hinzugefügt, das dieselbe nameund valuedie Schaltfläche "Senden" verwendet.

BEARBEITEN: Die folgende Version ist leichter zu lesen. Außerdem werden zuvor angehängte ausgeblendete Felder entfernt (im Fall des zweimaligen Absendens desselben Formulars, was bei Verwendung von AJAX durchaus möglich ist).

Verbesserter Code:

$(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);
});
J. Bruni
quelle
1+ Das hat es für mich getan. Vielen Dank!
Lennart Rolland
Es sieht so aus, als ob alle <button/>s dasselbe nameAttribut haben. Ich würde eine Klasse verwenden und in Ihrer darauf verweisen .remove().
Binki
@binki: nein, das tut es nicht. Auf jeden Fall kann jeder Entwickler die Lösung an seine eigenen Bedürfnisse anpassen.
J. Bruni
jsfiddle.net/binki/d8ecv zeigt, was ich mit dem nameAttribut meine . Wenn das Formular wiederverwendet wird und Übermittlungseingaben mit unterschiedlichen Namen enthält, können die alten Eingaben das Formular überladen.
Binki
Jetzt sehe ich ... Ich werde meine Antwort aktualisieren. (Tatsächlich habe ich Ihrem Kommentar nicht viel Aufmerksamkeit geschenkt, da Sie das <button/>Element nicht erwähnt haben, während <input type="submit" />es im Code verwendet wird ...)
J. Bruni
2

Ich habe einige der bereitgestellten Beispiele ausprobiert, aber sie haben für unsere Zwecke nicht funktioniert.

Hier ist eine Geige zu zeigen: http://jsfiddle.net/7a8qhofo/1/

Ich war mit einem ähnlichen Problem konfrontiert, und so haben wir das Problem in unseren Formularen gelöst.

$(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
    });
});
Rudi Strydom
quelle
2

( Veranstaltung )

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;">
user3126867
quelle
1

Sie können dies mit "event.originalEvent.x" und "event.originalEvent.y" versuchen:

<!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>
andres descalzo
quelle
"yikes"?, es funktioniert, es funktioniert nicht, es ist nützlich, nicht nützlich, ...? Ich spreche kein gutes Englisch
andres descalzo
@hunter Wie kann ich Ihren Kommentar mehrmals positiv bewerten?
Tom Auger
0

jQuery scheint diese Daten für das Übermittlungsereignis nicht bereitzustellen. Sieht so aus, als wäre die von Ihnen vorgeschlagene Methode die beste Wahl.

Matchu
quelle
0

Nur eine andere Lösung, da keine andere meine Anforderungen erfüllte. Der Vorteil ist, dass Klick und Tastendruck (Enter und Leertaste) erkannt werden.

// 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({
            // ...
        })
    }
}

Das hat bei mir am besten funktioniert.

Roland
quelle
0

Mit einem spezifischeren Ereignishandler und JQuery ist Ihr Ereignisobjekt die Schaltfläche, auf die geklickt wird. Bei Bedarf können Sie das Delegierungsformular auch von dieser Veranstaltung erhalten.

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

Dieses Dokument enthält alles, was Sie für den Einstieg benötigen. JQuery Doc .


quelle
0

Ich schreibe diese Funktion, die mir hilft

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;

};

und dann verwenden

var data= PupulateFormData($("form"));
BabiBN
quelle