Как я могу получить кнопку, которая вызвала отправку из события отправки формы?


110

Я пытаюсь найти значение кнопки отправки, которая запустила форму для отправки

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

});

Я мог бы запустить событие $ ("input [type = submit]"). Click () для каждой кнопки и установить некоторую переменную, но это кажется менее элегантным, чем то, как вытаскивать кнопку из формы при отправке.


2
Обратите внимание, что такой кнопки не обязательно. Подойдет сценарий formobj.submit(). Я думаю, что события щелчка - это то, что нужно.
Джейсон Орендорф

1
Для современных браузеров теперь есть то, event.submitterчто дает вам то <button>или <input type="submit">иное нажатие.
gfv

Ответы:


107

Я использовал, document.activeElementкак показано в этом ответе: как получить сфокусированный элемент с помощью 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 */
    }
});

Я пользуюсь тем фактом, что кнопка всегда оказывается в фокусе после нажатия на нее. Это не сработает, если вы сделаете blur()сразу после щелчка.

@Doin обнаружил еще один недостаток. Если пользователь отправляет форму через enterтекстовое поле, значение document.activeElementне устанавливается. Вам нужно будет следить за этим самостоятельно, обрабатывая keypressсобытия input[type="text"]и тому подобное.

Обновление 2017-01: для моей библиотеки Hyperform я решил не использовать, activeElementа улавливать все события, которые приводят к отправке формы. Код для этого есть на Github.

Если вы используете Hyperform, вы получите доступ к кнопке, запускающей отправку:

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

1
MDN говорит да. (FF3, IE4, Chrome 2, Safari 4, Opera 9)
Boldewyn 05

1
Это должен быть ответ.
Рой Намир 05

2
Хммм ... это работает, если форма отправлена ​​через [Enter]? Spec говорит, что это должно быть эквивалентно нажатию кнопки отправки по умолчанию, но я не уверен, что она останется активным элементом или нет.
Doin

8
К сожалению, вы не можете полагаться только наactiveElement , потому что «отправитель» может быть определен: A. Через аутентичную активацию щелчком ( щелчок непосредственно с помощью мыши или клавиатуры Пробел / Ввод); Б. Через активацию синтетическим щелчком ( buttonElement.click()или buttonElement.dispatch(new MouseEvent(...))без потери фокуса); C. через форму неявно отправка (взаимодействие клавиатуры с другим полем формы) D. ни на что, когдаformElement.submit()
mems

5
Просто примечание, чтобы держать вещи в курсе. На данный момент Safari устанавливает activeElement в тело документа при нажатии кнопки отправки. Я столкнулся с этой проблемой в Safari 9.1
coderkevin

35

Я реализовал это и полагаю, что так и будет.

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

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

    // DO WORK

});

и это событие кнопки отправки, которое устанавливает его

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

Спасибо за ответы, но это не так уж и элегантно ...


1
Не поддерживает кроссбраузер / несколько кнопок отправки.
user1610743 02

2
Гарантируется ли, что событие щелчка запускается до события отправки формы? Я бы предложил предоставить форме doNotSubmitкласс, внутри функции отправки проверьте, не существует ли класс (иначе не отправляйте), внутри события щелчка удалите класс формы doNotSubmitи выполните триггер $ (''. MyForm '). ('Отправить'); после добавления значения кнопки отправки в качестве скрытого поля
Hafenkranich

2
@Hafenkranich В некоторых редких случаях в Chrome событие щелчка запускается ПОСЛЕ события отправки.
romanoza

@roamnoza это именно то, с чем я тоже столкнулся.
Hafenkranich

2
@ j4k3 Есть лучшее решение? Ответу 8 лет
охотник

10

Я создал тестовую форму и с помощью Firebug нашел способ получить значение;

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

К сожалению, только Firefox поддерживает это событие.


5
IE не имеет этого свойства (explicitOriginalTarget)
андрес дескальцо

1
Старый добрый IE все испортил, прошел через Firebug и не смог увидеть другие значения объектов, которые можно было бы использовать, но просто забыл об альтернативных браузерах. Не удивлен, узнав, что это не так, придется проверить Chrome.
Дэйв Андерсон,

11
Только Firefox поддерживает это событие.
Andy E

В общем, в HTML есть что-то, чего нельзя сделать в JS ... Mozilla решила реализовать недостающую функцию, и никто не последовал ее примеру? Вот почему мы не можем иметь приятные вещи
aross

7

Теперь submitterв событии отправки есть стандартное свойство.
Уже реализовано в Firefox 75 !

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

Для браузеров, которые его не поддерживают, используйте этот полифилл :

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

6

Вот подход, который мне кажется более понятным.

Во-первых, для любых форм:

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

Когда это событие щелчка запускается для формы, оно просто записывает исходную цель (доступную в объекте события) для последующего доступа. Это довольно широкий ход, так как он срабатывает при любом щелчке в любом месте формы. Комментарии по оптимизации приветствуются, но я подозреваю, что они никогда не вызовут заметных проблем.

Затем в $ ('form'). Submit () вы можете узнать, что было нажато последним, с чем-то вроде

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

4

По этой ссылке объект Event содержит поле Event.target, в котором:

Возвращает строку, представляющую объект, инициировавший событие.

Я только что создал страницу, проверяющую, что это за значение, и похоже, что это представление предназначено для самой формы, а не для нажатой кнопки. Другими словами, Javascript не предоставляет средства для определения нажатой кнопки.

Насколько Дэйва Андерсона решения , это может быть хорошей идеей для тестирования , что в нескольких браузерах перед ее использованием. Возможно, это сработает нормально, но я не могу сказать ни слова.


1
targetВозвращает всю форму. Таким образом, к сожалению, не помогает обнаружить правильную кнопку отправки.
Hafenkranich 04

Я говорю об этом в своем ответе, @Hafenkranich.
cmptrgeekken 06

Event.targetне строка. Это EventTargetобъект, которым в данном случае является сама отправленная форма.
Аксели

4

Один чистый подход - использовать событие щелчка на каждой кнопке формы. Ниже представлена ​​HTML-форма с кнопками сохранения, отмены и удаления:

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

Ниже приведен jquery. Я отправляю соответствующее «действие» той же функции сервера в зависимости от того, какая кнопка была нажата («сохранить» или «удалить»). Если нажата кнопка «Отмена», я просто перезагружаю страницу.

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

Я искал и нашел несколько способов получить кнопку отправки name+value на сервер с помощью jQuery + AJAX. Они мне не очень нравились ...

Одним из лучших было представленное здесь охотничье решение!

Но я написал еще один.

Хочу поделиться, потому что это хорошо и, по мере необходимости, работает и с формами, загруженными через ajax (после 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'));
});

Просто! Когда нажимается кнопка отправки, в форму добавляется скрытое поле, используя то же самое nameи valueкнопки отправки.

РЕДАКТИРОВАТЬ: версию ниже легче читать. Кроме того, он позаботится об удалении ранее добавленных скрытых полей (в случае отправки одной и той же формы дважды, что вполне возможно при использовании AJAX).

Улучшенный код:

$(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+ Это помогло мне. Спасибо!
Леннарт Роллан

Похоже, это зависит от того, что все <button/>используют один и тот же nameатрибут. Я бы использовал класс и сослался бы на него в вашем .remove().
binki

@binki: нет, это не так. В любом случае, каждый разработчик может адаптировать решение под свои нужды.
J. Bruni

jsfiddle.net/binki/d8ecv показывает, что я имею в виду в отношении nameатрибута. Если форма используется повторно и содержит входные данные для отправки с разными именами, старые входные данные могут загромождать форму.
binki

Теперь понятно ... Обновлю свой ответ. (На самом деле, я не обратил особого внимания на ваш комментарий из-за не связанного с этим факта, что вы упоминаете <button/>элемент, а <input type="submit" />он используется в коде ...)
Дж. Бруни

2

Я пробовал некоторые из представленных примеров, но они не работали для наших целей.

Вот скрипка, которую нужно показать: http://jsfiddle.net/7a8qhofo/1/

Я столкнулся с аналогичной проблемой, и именно так мы решили ее в наших формах.

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

( мероприятие )

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

вы можете попробовать этот способ с "event.originalEvent.x" и "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>

"yikes" ?, это работает, это не работает, это полезно, не полезно, ...? , Я плохо говорю по-английски
andres descalzo

@hunter, как мне проголосовать за ваш комментарий несколько раз?
Tom Auger

0

jQuery, похоже, не предоставляет эти данные о событии отправки. Похоже, предложенный вами метод - ваш лучший выбор.


0

Еще одно решение, поскольку ни одно другое не соответствовало моим требованиям. Преимущество состоит в том, что обнаруживаются щелчки и нажатия клавиш (ввод и пробел) .

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

Это сработало для меня лучше всего.


0

С более конкретным обработчиком событий и JQuery для вашего объекта события нажимается кнопка. При необходимости вы также можете получить форму делегирования от этого мероприятия.

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

В этом документе есть все необходимое для начала работы. JQuery Doc .


0

Я пишу эту функцию, которая мне помогает

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;

};

а затем используйте

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

0

Там есть податель свойство для формы в SubmitEvent . Однако в настоящее время это не работает в 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);
}

Другой подход, который работает во всех браузерах. Однако вы должны полагаться на formэлемент, а не на eventобъект. Это в основном добавляет свойство «submitter» к объекту элемента формы, на которое можно ссылаться позже при отправке формы.

<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);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.