Jak mogę uzyskać przycisk, który spowodował przesłanie ze zdarzenia przesyłania formularza?

110

Próbuję znaleźć wartość przycisku przesyłania, który spowodował przesłanie formularza

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

});

Mógłbym prawdopodobnie uruchomić zdarzenie $ ("input [type = submit]"). Click () dla każdego przycisku i ustawić jakąś zmienną, ale wydaje się to mniej eleganckie niż wyciągnięcie przycisku z formularza podczas przesyłania.

myśliwy
źródło
2
Zwróć uwagę, że niekoniecznie istnieje taki przycisk. Skrypt może wystarczyć formobj.submit(). Myślę, że zdarzenia związane z kliknięciami są do zrobienia.
Jason Orendorff
1
W przypadku nowoczesnych przeglądarek jest teraz, event.submitterktóry daje kliknięcie <button>lub <input type="submit">.
gfv

Odpowiedzi:

107

Wykorzystałem, document.activeElementjak naszkicowałem w tej odpowiedzi: Jak uzyskać skoncentrowany element za pomocą 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 */
    }
});

Korzystam z tego, że przycisk jest zawsze aktywnym elementem po kliknięciu. To nie zadziała, jeśli zrobisz to blur()zaraz po kliknięciu.

@Doin zauważył kolejną wadę. Jeśli użytkownik prześle formularz enterw polu tekstowym, document.activeElementopcja nie jest ustawiona. Musisz sam na to uważać, obsługując keypresszdarzenia w programie input[type="text"]i tym podobne.

Aktualizacja 2017-01: W mojej bibliotece Hyperform zdecydowałem się nie używać, activeElementale przechwytywać wszystkie zdarzenia, które prowadzą do przesłania formularza. Kod do tego znajduje się na Github.

Jeśli zdarzy ci się użyć Hyperform, w ten sposób uzyskasz dostęp do przycisku, który uruchomił przesyłanie:

$(form).on('submit', function(event) {
  var button = event.submittedVia;
});
Boldewyn
źródło
1
MDN mówi tak. (FF3, IE4, Chrome 2, Safari 4, Opera 9)
Boldewyn
1
To powinna być odpowiedź.
Royi Namir
2
Hmmm ... czy to działa, jeśli formularz jest przesyłany przez [Enter]? Spec mówi, że powinno to być równoznaczne z kliknięciem domyślnego przycisku przesyłania, ale nie jestem pewien, czy pozostawia go jako aktywny element, czy nie.
Doin
8
Niestety nie można polegać tylko naactiveElement , ponieważ „przesyłającego” można zdefiniować: A. Poprzez autentyczną aktywację kliknięciem (kliknięcie bezpośrednio myszą lub klawiaturą Spacja / Enter); B. Poprzez aktywację kliknięciem syntetycznym ( buttonElement.click()lub buttonElement.dispatch(new MouseEvent(...))bez sprawdzania ostrości); C. niejawne poddanie się przez formularz (interakcja klawiatury z polem innego formularza) D. do żadnego, kiedyformElement.submit()
memy
5
Tylko uwaga, aby zachować aktualność. Od teraz Safari ustawia activeElement na treść dokumentu po kliknięciu przycisku przesyłania.
Natknąłem się
35

Wdrożyłem to i przypuszczam, że to wystarczy.

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

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

    // DO WORK

});

i to jest zdarzenie przycisku przesyłania, które go konfiguruje

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

Dzięki za odpowiedzi, ale to nie jest strasznie nieeleganckie ...

myśliwy
źródło
1
Brak możliwości obsługi wielu przeglądarek / przycisków przesyłania.
user1610743,
2
Czy jest zagwarantowane, że zdarzenie kliknięcia zostanie uruchomione przed zdarzeniem przesłania formularza? Proponuję nadać formularzowi doNotSubmitklasę, wewnątrz funkcji przesyłania sprawdzić, czy klasa nie istnieje (w przeciwnym razie nie przesyłaj), wewnątrz zdarzenia click usuń klasę formularza doNotSubmiti wykonaj $ (''. MyForm '). Trigger ('Zatwierdź'); po dodaniu wartości przycisku przesyłania jako ukrytego pola
Hafenkranich
2
@Hafenkranich W rzadkich przypadkach w Chrome zdarzenie kliknięcia jest wywoływane PO zdarzeniu przesłania.
romanoza
@roamnoza właśnie to spotkałem.
Hafenkranich
2
@ j4k3 Masz lepsze rozwiązanie? Ta odpowiedź ma 8 lat
myśliwy
10

Stworzyłem formularz testowy i używając Firebuga znalazłem w ten sposób, aby uzyskać wartość;

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

Niestety tylko Firefox obsługuje to zdarzenie.

Dave Anderson
źródło
5
IE nie ma tej własności (explicitOriginalTarget)
andres Descalzo
1
Dobry stary IE zepsuł to, przeszedł przez Firebuga i nie mógł zobaczyć żadnych innych wartości obiektów do użycia, ale po prostu zapomniał o alternatywnych przeglądarkach. Nie jest zdziwiony, że nie, będzie musiał sprawdzić Chrome.
Dave Anderson
11
Tylko Firefox obsługuje to zdarzenie.
Andy E
Więc zasadniczo jest coś w HTML, czego nie da się zrobić w JS ... Mozilla zdecydowała się zaimplementować brakującą funkcję i nikt nie poszedł za jej przykładem? Dlatego nie możemy mieć fajnych rzeczy
około
7

submitterZdarzenie przesyłania zawiera teraz standardową właściwość.
Już zaimplementowano w Firefoksie 75 !

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

W przypadku przeglądarek, które go nie obsługują, użyj tego wypełnienia :

!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
źródło
6

Oto podejście, które wydaje się czystsze dla moich celów.

Po pierwsze, dla wszystkich formularzy:

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

Gdy to zdarzenie kliknięcia jest uruchamiane dla formularza, po prostu rejestruje pierwotny cel (dostępny w obiekcie zdarzenia), aby uzyskać do niego dostęp później. To dość szerokie pociągnięcie, ponieważ będzie uruchamiane po każdym kliknięciu w dowolnym miejscu formularza. Komentarze dotyczące optymalizacji są mile widziane, ale podejrzewam, że nigdy nie spowoduje to zauważalnych problemów.

Następnie w $ ('form'). Submit (), możesz zapytać, co zostało ostatnio kliknięte, na przykład

if ($(this).data('clicked').is('[name=no_ajax]')) xhr.abort();
Jonathan Camenisch
źródło
4

Zgodnie z tym linkiem obiekt Event zawiera pole Event.target, które:

Zwraca ciąg znaków reprezentujący obiekt, który zainicjował zdarzenie.

Właśnie utworzyłem stronę sprawdzającą, jaka jest ta wartość i wygląda na to, że reprezentacja dotyczy samego formularza, a nie klikniętego przycisku. Innymi słowy, JavaScript nie zapewnia możliwości określenia klikniętego przycisku.

Jeśli chodzi o rozwiązanie Dave'a Andersona , dobrym pomysłem może być przetestowanie go w wielu przeglądarkach przed użyciem. Możliwe, że to zadziała, ale nie mogę powiedzieć ani jednej drogi.

cmptrgeekken
źródło
1
targetPowraca cały formularz. Dlatego niestety nie pomaga wykryć właściwego przycisku przesyłania.
Hafenkranich
To samo mówię w mojej odpowiedzi @Hafenkranich.
cmptrgeekken,
Event.targetnie jest ciągiem. Jest to EventTargetobiekt, który w tym przypadku jest samym przesłanym formularzem.
Akseli
4

Jednym prostym podejściem jest użycie zdarzenia click na każdym przycisku formularza. Poniżej znajduje się formularz html z przyciskami Zapisz, Anuluj i Usuń:

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

Poniżej znajduje się jQuery. Wysyłam odpowiednią „akcję” do tej samej funkcji serwera w zależności od tego, który przycisk został kliknięty („zapisz” lub „usuń”). Po kliknięciu przycisku „anuluj” po prostu ponownie ładuję stronę.

$('.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
źródło
3

Szukałem i znalazłem kilka sposobów na otrzymanie przycisku przesyłania name+ valuewysłanego do serwera za pomocą jQuery + AJAX. Nie bardzo mi się podobały ...

Jednym z najlepszych było zaprezentowane tutaj rozwiązanie myśliwskie!

Ale sam napisałem inny.

Chcę się udostępnić, ponieważ jest dobry i, jak potrzebowałem, działa również z formularzami ładowanymi przez ajax (po 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'));
});

Prosty! Po kliknięciu przycisku przesyłania ukryte pole jest dodawane do formularza za pomocą tego samego przycisku namei valueprzycisku przesyłania.

EDYCJA: Poniższa wersja jest bardziej czytelna. Dba również o usunięcie dołączonych wcześniej pól ukrytych (w przypadku dwukrotnego przesłania tego samego formularza, co jest doskonale możliwe przy wykorzystaniu AJAX).

Ulepszony kod:

$(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
źródło
1+ Zrobiło to dla mnie. Dzięki!
Lennart Rolland
Wygląda na to, że wszystkie <button/>mają ten sam nameatrybut. Użyłbym klasy i odniósłbym się do tego w twoim .remove().
binki
@binki: nie, nie działa. Zresztą każdy programista może dostosować rozwiązanie do własnych potrzeb.
J. Bruni,
jsfiddle.net/binki/d8ecv pokazuje, co mam na myśli w odniesieniu do nameatrybutu. Jeśli formularz jest używany ponownie i zawiera dane wejściowe przesyłania z różnymi nazwami, stare dane wejściowe mogą zaśmiecać formularz.
binki
Teraz widzę ... Zaktualizuję swoją odpowiedź. (Właściwie nie zwróciłem uwagi na Twój komentarz ze względu na niepowiązany fakt, że wspomniałeś o <button/>elemencie, podczas gdy <input type="submit" />jest on używany w kodzie ...)
J. Bruni
2

Wypróbowałem niektóre z podanych przykładów, ale nie działały one dla naszych celów.

Oto skrzypce do pokazania: http://jsfiddle.net/7a8qhofo/1/

Miałem podobny problem i tak rozwiązaliśmy ten problem w naszych formularzach.

$(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
źródło
2

(wydarzenie)

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
źródło
1

możesz spróbować w ten sposób z „event.originalEvent.x” i „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>
andres descalzo
źródło
"yikes" ?, działa, nie działa, jest przydatne, nieprzydatne, ...? , Nie mówię dobrze po angielsku
andres descalzo
@hunter jak wielokrotnie zagłosować za Twoim komentarzem?
Tom Auger
0

Wydaje się, że jQuery nie dostarcza tych danych w zdarzeniu przesyłania. Wygląda na to, że zaproponowana przez Ciebie metoda jest najlepszym rozwiązaniem.

Matchu
źródło
0

Po prostu inne rozwiązanie, ponieważ żadne inne nie spełniało moich wymagań. Zaletą jest to, że wykrywane są kliknięcia i naciśnięcia klawiszy (enter i spacja) .

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

To działało najlepiej dla mnie.

roland
źródło
0

W przypadku bardziej szczegółowej procedury obsługi zdarzeń i JQuery, obiekt zdarzenia jest klikany. W razie potrzeby możesz również pobrać formularz delegowania z tego wydarzenia.

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

Ten dokument zawiera wszystko, czego potrzebujesz, aby rozpocząć. JQuery Doc .


źródło
0

Piszę tę funkcję, która mi pomaga

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;

};

a następnie Użyj

var data= PupulateFormData($("form"));
BabiBN
źródło
0

Istnieje właściwość przesyłającego dla SubmitEvent formularza . Jednak w chwili obecnej nie działa to w przeglądarce Safari.

<form id="form">
    <button value="add" type="submit">Add</button>
    <button value="remove" type="submit">Remove</button>
</form>
let form = document.getElementById('form');

form.onsubmit = (event) => {
    e.preventDefault();
    console.log(e.submitter.type);
}

Inne podejście, które działa w różnych przeglądarkach. Musisz jednak polegać na formelemencie zamiast na eventobiekcie. Zasadniczo dodaje to właściwość „przesyłający” do obiektu elementu formularza, do którego można się później odwołać podczas przesyłania formularza.

<form id="form">
    <button onclick="this.form.submitter = 'add'" type="submit">Add</button>
    <button onclick="this.form.submitter = 'remove'" type="submit">Remove</button>
</form>
let form = document.getElementById('form');

form.onsubmit = (event) => {
    e.preventDefault();
    console.log(form.submitter);
}
Nur Ilyas
źródło