jQuery: как узнать, какая кнопка была нажата при отправке формы?

227

У меня есть .submit()событие для отправки формы. У меня также есть несколько форм на странице, но только один здесь для этого примера. Я хотел бы знать, какая кнопка отправки была нажата без применения .click()события к каждому из них.

Вот настройки:

<html>
<head>
  <title>jQuery research: forms</title>
  <script type='text/javascript' src='../jquery-1.5.2.min.js'></script>
  <script type='text/javascript' language='javascript'>
      $(document).ready(function(){
          $('form[name="testform"]').submit( function(event){ process_form_submission(event); } );
      });
      function process_form_submission( event ) {
          event.preventDefault();
          //var target = $(event.target);
          var me = event.currentTarget;
          var data = me.data.value;
          var which_button = '?';       // <-- this is what I want to know
          alert( 'data: ' + data + ', button: ' + which_button );
      }
  </script>
</head>
<body>
<h2>Here's my form:</h2>
<form action='nothing' method='post' name='testform'>
  <input type='hidden' name='data' value='blahdatayadda' />
  <input type='submit' name='name1' value='value1' />
  <input type='submit' name='name2' value='value2' />
</form>
</body>
</html>

Живой пример на jsfiddle

Помимо применения события .click () к каждой кнопке, есть ли способ определить, какая кнопка отправки была нажата?

hawkexp
источник
2
Ирония в том, что эта информация тривиальна для определения серверной части.
Нил
5
@Neil Нет, если вы отправляете форму через $ .ajax () и serializeArray () в форме.
Аарон
1
Как насчет размещения слушателя на кнопках отправки и отправки формы вручную.
JMRC
1
Как насчет просмотра сериализованной версии данных формы и сопоставления с кнопками name?
Августин Ридингер

Ответы:

235

Я задал тот же вопрос: как я могу получить кнопку, которая вызвала отправку из события отправки формы?

Я закончил тем, что придумал это решение, и оно работало довольно хорошо:

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

В вашем случае с несколькими формами вам, возможно, придется немного подправить, но это все равно должно применяться

охотник
источник
11
+1 Отличное решение. Возможно, вы захотите добавить оператор, который сбрасывает атрибут clicked на false по всем кнопкам в случае, если отправка формы обрабатывается Ajax-способом, и вы хотите избежать повторного нажатия кнопки, предварительно нажатой ранее.
Чанду
1
О, я вижу. Вы добавляете свой собственный атрибут "clicked". Я искал "кликнул" логическое значение и не мог найти нигде. Я никогда не думал сделать это сам. Отличная идея!
hawkexp
9
Помните, что это работает только с элементами ввода, а не с кнопками.
Bob.at.Indigo.Health
1
Это не нужно в Chrome с элементами кнопок. Я просто обрабатываю событие on submit, создаю объект FormData из формы, и он всегда включает значение кнопки, на которую нажали. FireFox НЕ демонстрирует такое поведение и вместо этого вообще не отправляет значение кнопки. Похоже, что Chrome выполняет что-то вроде вышеупомянутого решения автоматически, запоминает, какая кнопка была нажата, и автоматически включает ее в данные формы. Конечно, это отсутствие стандартного поведения (в любом случае, мучающего все в JavaScript, поэтому я не удивлен) делает эту функцию бесполезной.
Трийнко
1
Также рассмотрите возможность добавления селектора «button [type = submit]» (через запятую), так как элементы submit не обязательно должны быть тегами ввода.
Kyselejsyreček
91

Я обнаружил, что это работает.

$(document).ready(function() {
    $( "form" ).submit(function () {
        // Get the submit button element
        var btn = $(this).find("input[type=submit]:focus" );
    });
}
Стан
источник
12
это решение хорошо работает в Chrome, но не может работать в Safari, оно будет возвращать неопределенный объект, а не объект кнопки
г-н Сан Лин
1
@Krinkle Я так закодировал это, чтобы показать самый общий из возможных способов. Я думаю, что разработчики достаточно умны, чтобы оптимизировать его под свои вкусы.
Стен
Чище, чем другие решения. Все еще не нашли решение, которое работает при нажатии Enter, хотя
andrewtweber
Этот ответ не будет работать всегда. На самом деле вам нужна нажатая кнопка, а не сфокусированная (так как фокусное действие не является щелчком). Выбранный ответ (охотника) является правильным.
Василь Попов
У меня есть событие щелчка на кнопках отправки и отправки событий в их формах ... последнее вызывает первое. Я использовал это, чтобы выяснить источник события. В некоторых браузерах, нажимая кнопку, вы получаете кнопку как сфокусированную, в других вы ничего не получаете. Во всех браузерах, которые я тестировал, нажатие клавиши ввода во время ввода удерживает фокус ввода.
notacouch
65

Это работает для меня:

$("form").submit(function() {
   // Print the value of the button that was clicked
   console.log($(document.activeElement).val());
}
seddonym
источник
3
Это было полезно, чтобы получить idиз activeElement, я$(document.activeElement).attr('id');
Миколай
9
Для чего бы это ни стоило, вам не нужно использовать jQuery для получения идентификатора - еще проще использовать чистый Javascript:document.activeElement.id
Ник Ф
5
Обратите внимание, что в Safari это не работает должным образом. :(
rinogo
@rinogo: что происходит в Safari?
Crescent Fresh
1
В Safari document.activeElementнет входа. В моем случае это модальный div (который содержит форму).
mgalgs
46

Когда форма отправлена:

  • document.activeElement даст вам кнопку отправки, которая была нажата.

  • document.activeElement.getAttribute('value') даст вам значение этой кнопки.

Ник Ф
источник
2
Обратите внимание, что в Safari это не работает должным образом. :(
rinogo
Я не знаю, как насчет Safari, но на Chrome работал хорошо :) Спасибо!
Ингус
Работает в Chrome 63 и IE11
сэр Криспалот
У меня была запущена ненавязчивая проверка jquery, и она перехватывает перед этим и устанавливает неверный ввод как activeElement вместо кнопки.
Peheje
28

Вот подход, который кажется чище для моих целей.

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

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

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

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

if ($(this).data('clicked').is('[name=no_ajax]')) xhr.abort();
Джонатан Камениш
источник
Что если это событие отправки формы вместо клика?
Тони
1
@ Тони, прости, я раньше не видел твой вопрос. Этот ответ целиком относится к форме представления. Кнопки «Отправить» тоже нажимаются, и, таким образом, они запускают событие нажатия.
Джонатан Камениш
2
Передавайте этот ответ поверх ответа охотника, так как события отправки формы запускаются перед любыми событиями щелчка дочернего элемента. Это вызывает трудности, когда событие отправки вашей формы отменяется return false, тогда как этот метод работает правильно, поскольку щелчок привязан к форме, а не к ее дочерним элементам.
Поспи
7
Это не может правильно обработать случай, когда форма отправляется с помощью других средств, кроме щелчка (например, нажав Enter). Когда форма отправляется другим способом, это первая кнопка отправки, которая вызвала событие отправки, а не последняя нажатая.
quietmint
После этого пропущена точка с запятой, ... $(event.target))но редактирование невозможно, так как изменения должны быть> 6 символов
Hafenkranich
13

Вау, некоторые решения могут быть сложными! Если вы не возражаете против использования простого глобального, просто воспользуйтесь тем, что событие нажатия кнопки ввода срабатывает первым. Далее можно отфильтровать селектор $ ('input') для одной из многих форм, используя $ ('# myForm input').

    $(document).ready(function(){
      var clkBtn = "";
      $('input[type="submit"]').click(function(evt) {
        clkBtn = evt.target.id;
      });

      $("#myForm").submit(function(evt) {
        var btnID = clkBtn;
        alert("form submitted; button id=" + btnID);
      });
    });
lawnbowler
источник
12

Я нашел лучшее решение

$(document.activeElement).attr('id')

Это не только работает на входах, но и на тегах кнопок. Также он получает идентификатор кнопки.

Томас Уильямс
источник
Черт, я должен посмотреть, работает ли моя страница в Safari, дох. Почему Safari всегда должен быть таким сложным. Спасибо за это. Собираюсь проверить, когда я вернусь домой
Томас Уильямс
Это не работает для меня в Safari. Нажмите слушателя на кнопку в теле вызывает .submit на форме. Внутри $(document.activeElement).attr('id')возвращается обработчик отправкиundefined
dyodji
7

Другое возможное решение - добавить скрытое поле в форму:

<input type="hidden" id="btaction"/>

Затем в функцию ready добавьте функции для записи, какая клавиша была нажата:

$('form#myForm #btnSubmit').click(function() {
    $('form#myForm #btaction').val(0);
});

$('form#myForm #btnSubmitAndSend').click(function() {
    $('form#myForm #btaction').val(1);
});

$('form#myForm #btnDelete').click(function() {
    $('form#myForm #btaction').val(2);
});

Теперь в форме обработчик представления прочитайте скрытую переменную и решите на ее основе:

var act = $('form#myForm #btaction').val();
wmac
источник
6

Основываясь на том, что сделали Стэн и Янн-ч, но по умолчанию используется первая кнопка. Прелесть этого общего подхода заключается в том, что он улавливает как щелчок, так и клавишу ввода (даже если фокус был не на кнопке. Если вам нужно разрешить ввод в форме, просто ответьте на это, когда кнопка находится в фокусе ( т.е. ответ Стэна.) В моем случае я хотел разрешить вводу отправлять форму, даже если текущий фокус пользователя был на текстовом поле.

Я также использовал атрибут name, а не id, но это тот же подход.

var pressedButtonName =
     typeof $(":input[type=submit]:focus")[0] === "undefined" ?
     $(":input[type=submit]:first")[0].name :
     $(":input[type=submit]:focus")[0].name;
andrewmo
источник
Так что если вы переместите фокус на вторую кнопку с помощью клавиши TAB и нажмете RETURN, то по умолчанию будет установлена ​​первая кнопка ...
FrancescoMM
5

Этот работал для меня

$('#Form').submit(function(){
var btn= $(this).find("input[type=submit]:focus").val();
alert('you have clicked '+ btn);

}
Сахеб Мондал
источник
Это заслуживает медали!
Мартин Зварик
4

Если вы не имеете в виду, что не добавляете событие .click, что вы не хотите иметь отдельные обработчики для этих событий, вы можете обрабатывать все клики (отправки) в одной функции:

$(document).ready(function(){
  $('input[type="submit"]').click( function(event){ process_form_submission(event); } );
});

function process_form_submission( event ) {
  event.preventDefault();
  //var target = $(event.target);
  var input = $(event.currentTarget);
  var which_button = event.currentTarget.value;
  var data = input.parents("form")[0].data.value;
//  var which_button = '?';       // <-- this is what I want to know
  alert( 'data: ' + data + ', button: ' + which_button );
}
jcane86
источник
Неплохая идея. Будет ли это работать для любого количества форм на странице?
hawkexp
@ ястреб да, это должно. Я не знаю, является ли это желаемым поведением, но ваш код на самом деле не отправляет форму, так что мой тоже нет. Если вы хотите отправить его, просто удалите event.preventDefaultили сделайте что-нибудь подобное input.parents("form")[0].submit().
jcane86
И если вы отправите без щелчка (клавиша возврата?), Это будет полный беспорядок ..
FrancescoMM
4

Поскольку я не могу комментировать принятый ответ, я привожу здесь измененную версию, которая должна учитывать элементы, которые находятся вне формы (то есть: прикреплены к форме с помощью formатрибута). Это для современного браузера: http://caniuse.com/#feat=form-attribute . closest('form') Используются в качестве запасного варианта для неподдерживаемого formатрибута

$(document).on('click', '[type=submit]', function() {
    var form = $(this).prop('form') || $(this).closest('form')[0];
    $(form.elements).filter('[type=submit]').removeAttr('clicked')
    $(this).attr('clicked', true);
});

$('form').on('submit', function() {
    var submitter = $(this.elements).filter('[clicked]');
})
user3074069
источник
Это действительно должен быть выбранный ответ. Я бы только добавил, что правило должно быть"button,[type=submit]"
Wil
@ Но не все кнопки являются кнопками отправки, это зависит от их типа.
Птыскю
Да, но в отсутствие <input type = "submit">] каждый UA, который я когда-либо использовал, рассматривал тег <button> как триггер отправки формы, так что это поймает этот случай. Или автор может добавить предупреждение о том, что все отправляемые элементы должны иметь свойства [type = submit] ... одно из другого.
Wil
3
$("form input[type=submit]").click(function() {
    $("<input />")
        .attr('type', 'hidden')
        .attr('name', $(this).attr('name'))
        .attr('value', $(this).attr('value'))
    .appendTo(this)
});

добавить скрытое поле

anydasa
источник
Не работает в Firefox 30 / Windows 7. Примечание. В Firefox теперь требуется скрытое поле, так как оно может не отправлять значение отправки по щелчку, если оно отправлено с помощью jquery: this.submit () в событии on-submit. Я просто немного обеспокоен тем, что $ (this) .attr ('name') может работать не во всех браузерах.
user1610743
У меня Firefox 30 / Windows 7. У меня все работает отлично.
Anydasa
Не забудьте включить button[type=submit]и input[type=image].
rybo111
3

Для меня лучшим решением было следующее:

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

   // Get the button that was clicked       
   var submit = $(this.id).context.activeElement;

   // You can get its name like this
   alert(submit.name)

   // You can get its attributes like this too
   alert($(submit).attr('class'))

});
Джерамия Харланд
источник
3

Работая с этим превосходным ответом , вы можете проверить активный элемент (кнопку), добавить скрытый ввод в форму и при необходимости удалить его в конце обработчика отправки.

$('form.form-js').submit(function(event){
    var frm = $(this);
    var btn = $(document.activeElement);
    if(
        btn.length &&
        frm.has(btn) &&
        btn.is('button[type="submit"], input[type="submit"], input[type="image"]') &&
        btn.is('[name]')
    ){
        frm.append('<input type="hidden" id="form-js-temp" name="' + btn.attr('name') + '" value="' + btn.val() + '">');
    }

    // Handle the form submit here

    $('#form-js-temp').remove();
});

Примечание: я лично добавляю класс form-jsво все формы, которые отправляются через JavaScript.

rybo111
источник
2

Аналогично ответу Стэна, но:

  • если у вас более одной кнопки, вы должны получить только первую кнопку => [0]
  • если форма может быть отправлена ​​с помощью клавиши ввода, вы должны управлять по умолчанию => myDefaultButtonId

$(document).on('submit', function(event) {
    event.preventDefault();
    var pressedButtonId = 
         typeof $(":input[type=submit]:focus")[0] === "undefined" ? 
         "myDefaultButtonId" :
         $(":input[type=submit]:focus")[0].id;
    ...
 }
Янн-ч
источник
2

Это решение используется мной и работает очень хорошо:

// prevent enter key on some elements to prevent to submit the form
function stopRKey(evt) {
  evt = (evt) ? evt : ((event) ? event : null);
  var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
  var alloved_enter_on_type = ['textarea'];
  if ((evt.keyCode == 13) && ((node.id == "") || ($.inArray(node.type, alloved_enter_on_type) < 0))) {
    return false;
  }
}

$(document).ready(function() {
  document.onkeypress = stopRKey;
  // catch the id of submit button and store-it to the form
  $("form").each(function() {
    var that = $(this);

    // define context and reference
    /* for each of the submit-inputs - in each of the forms on
			 the page - assign click and keypress event */
    $("input:submit,button", that).bind("click keypress", function(e) {
      // store the id of the submit-input on it's enclosing form
      that.data("callerid", this.id);
    });
  });

  $("#form1").submit(function(e) {
    var origin_id = $(e.target).data("callerid");
    alert(origin_id);
    e.preventDefault();

  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form id="form1" name="form1" action="" method="post">
  <input type="text" name="text1" />
  <input type="submit" id="button1" value="Submit1" name="button1" />
  <button type="submit" id="button2" name="button2">
    Submit2
  </button>
  <input type="submit" id="button3" value="Submit3" name="button3" />
</form>

vasilenicusor
источник
1

Это помогло мне https://stackoverflow.com/a/17805011/1029257

Форма отправлена ​​только после нажатия кнопки «Отправить».

var theBtn = $(':focus');
if(theBtn.is(':submit'))
{
  // ....
  return true;
}

return false;
w4kskl
источник
1

Вот мое решение:

   $('#form').submit(function(e){   
        console.log($('#'+e.originalEvent.submitter.id));
        e.preventDefault();
    });
Рольдан
источник
0

Я также сделал решение, и оно работает довольно хорошо:
он использует jQuery и CSS


Во-первых, я создал быстрый CSS-класс, который можно встроить или в отдельный файл.

<style type='text/css'>
    .Clicked {
        /*No Attributes*/
    }
</style>


Затем, по событию click кнопки в форме, добавьте класс CSS к кнопке. Если у кнопки уже есть класс CSS, удалите его. (Нам не нужны два CSS-класса [на всякий случай]).

    // Adds a CSS Class to the Button That Has Been Clicked.
    $("form :input[type='submit']").click(function () 
    {
        if ($(this).hasClass("Clicked"))
        {
            $(this).removeClass("Clicked");
        }
        $(this).addClass("Clicked");
    });


Теперь протестируйте кнопку, чтобы увидеть, что у нее есть класс CSS, если у тестируемой кнопки нет CSS, то у другой кнопки будет.

    // On Form Submit
    $("form").submit(function ()
    {
        // Test Which Button Has the Class
        if ($("input[name='name1']").hasClass("Clicked"))
        {
            // Button 'name1' has been clicked.
        }
        else
        {
           // Button 'name2' has been clicked.
        }
    });

Надеюсь это поможет! Ура!

Джейсон Сидрас
источник
Не забудьте включить button[type=submit]и input[type=image].
rybo111
Вы должны удалить ссылки на стили и CSS - они здесь не актуальны. Кроме того, строки, в которых вы используете hasClass()и removeClass()избыточны, так как addClass()не добавят один и тот же класс дважды.
rybo111
0

Вы можете создать тип ввода = «скрытый» в качестве держателя для информации идентификатора кнопки.

<input type="hidden" name="button" id="button">
<input type="submit" onClick="document.form_name.button.value = 1;" value="Do something" name="do_something">

В этом случае форма передает значение «1» (идентификатор вашей кнопки) при отправке. Это работает, если onClick происходит до отправки (?), Но я не уверен, что это всегда так.

darekk
источник
0

Простой способ определить, какая кнопка <button> или <input type = "button" ...> нажата, - это проверить их 'id':

$("button").click(function() {
  var id = $(this).attr('id');
  ... 
});
Апостолоса
источник
0

Вот пример, в котором this.form используется для получения правильной формы, в которую отправляется объект, и поля данных для хранения последнего элемента, на который был сделан щелчок / фокус. Я также поместил код подтверждения в тайм-аут, чтобы убедиться, что события щелчка происходят до его выполнения (некоторые пользователи сообщали в комментариях, что в Chrome иногда событие щелчка вызывается после отправки).

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

Вы можете добавить кнопки type = "submit" к элементам, которые сохраняются при нажатии.

В демонстрации я установил красную рамку, чтобы показать выбранный элемент и предупреждение, которое показывает имя и значение / метку.

Вот скрипка

И вот (тот же) код:

Javascript:

$("form").submit(function(e) {
  e.preventDefault();
  // Use this for rare/buggy cases when click event is sent after submit
  setTimeout(function() {

    var $this=$(this);
    var lastFocus = $this.data("lastFocus");
    var $defaultSubmit=null;

    if(lastFocus) $defaultSubmit=$(lastFocus);

    if(!$defaultSubmit || !$defaultSubmit.is("input[type=submit]")) {
      // If for some reason we don't have a submit, find one (the first)
      $defaultSubmit=$(this).find("input[type=submit]").first();
    }

    if($defaultSubmit) {
      var submitName=$defaultSubmit.attr("name");
      var submitLabel=$defaultSubmit.val();

       // Just a demo, set hilite and alert
      doSomethingWith($defaultSubmit);
      setTimeout(function() {alert("Submitted "+submitName+": '"+submitLabel+"'")},1000);
    } else {
      // There were no submit in the form
    }

  }.bind(this),0);

});

$("form input").focus(function() {
  $(this.form).data("lastFocus", this);
});
$("form input").click(function() {
  $(this.form).data("lastFocus", this);
});

// Just a demo, setting hilite
function doSomethingWith($aSelectedEl) {
  $aSelectedEl.css({"border":"4px solid red"});
  setTimeout(function() { $aSelectedEl.removeAttr("style"); },1000);
}

DUMMY HTML:

<form>
<input type="text" name="testtextortexttest" value="Whatever you write, sir."/>
<input type="text" name="moretesttextormoretexttest" value="Whatever you write, again, sir."/>

<input type="submit" name="test1" value="Action 1"/>
<input type="submit" name="test2" value="Action 2"/>
<input type="submit" name="test3" value="Action 3"/>
<input type="submit" name="test4" value="Action 4"/>
<input type="submit" name="test5" value="Action 5"/>
</form>

DUMB CSS:

input {display:block}
FrancescoMM
источник
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"));
BabiBN
источник
0
$('form').submit(function (ev) {
  let clickedButton = ev.originalEvent.explicitOriginalTarget;
});
Александр Пауло
источник
-1

Вы хотите использовать window.event.srcElement.id следующим образом:

function clickTheButton() {

var Sender = window.event.srcElement;
alert("the item clicked was " + Sender.id)

}

для кнопки, которая выглядит как:

<input type="button" id="myButton" onclick="clickTheButton();" value="Click Me"/>

вы получите предупреждение, которое гласило: «элемент, на который нажали, был myButton.

В вашем улучшенном примере вы можете добавить window.event.srcElement к process_form_submission, и у вас будет ссылка на любой элемент, вызвавший процесс.

Cos Callis
источник
1
не используйте onclick для элементов, это устарело
Krzysztof Cygan
1
Это не работает для кнопок отправки, window.event.srcElement возвращает идентификатор формы.
333 МГц
@KrzysztofCygan Есть ли у вас источник этого?
Вард