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


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.