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 () на кожній кнопці, чи є спосіб визначити, на яку кнопку натискання було натиснуто?


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 Приємне рішення. Ви можете додати заяву, яка скидає атрибут, що натиснув, на помилковий через кнопок, якщо форма подання обробляється аяксним способом, і ви хочете уникнути отримання знову попередньо натиснутою кнопки.
— Чанду

1
О Я бачу. Ви додаєте власний атрибут "натиснутого". Я шукав у всьому "натиснутого" булевого і не міг знайти його ніде. Я ніколи не думав заробляти собі. Гарна ідея!
— hawkexp

9
Майте на увазі, що це працює лише з елементами введення, а не з кнопками.
— Bob.at.Indigo.Health

1
Це не потрібно в Chrome із елементами кнопки. Я просто обробляю подію on submit, будую з форми об’єкт FormData, і він завжди включає значення кнопки, яку натиснули. FireFox НЕ демонструє такої поведінки, і натомість взагалі не надсилає значення кнопки. Схоже, Chrome робить щось подібне до вищезазначеного рішення автоматично, запам'ятовуючи, яку кнопку було натиснуто, і включити її у дані форми автоматично. Звичайно, ця відсутність стандартної поведінки (все одно мучимо все в JavaScript, тому я не дивуюсь) робить цю функцію марною.
— Трайнко

1
Крім того, розгляньте можливість додавання селекторної кнопки "" [тип = подати] "(розділена комою), оскільки елементи подання не повинні бути тегами введення.
— 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

Ця відповідь працюватиме не завжди. Насправді вам потрібна натиснута кнопка, а не зосереджена (оскільки дія фокусування - це не дія кліку). Вибрана відповідь (мисливця) є правильною.
— Василь Попов

У мене є подія клацання на кнопках подання та надсилання подій на їхніх формах ... остання запускає першу. Я використав це для з'ясування джерела події. У деяких браузерах, натиснувши кнопку, ви отримаєте цільову увагу, а в інших - нічого. У всіх браузерах, які я перевіряв, натискання клавіші enter під час входу зберігає вхід зосередженим.
— notacouch

65

Це працює для мене:

$("form").submit(function() {
   // Print the value of the button that was clicked
   console.log($(document.activeElement).val());
}

3
Це було корисно, щоб отримати idз activeElement, я$(document.activeElement).attr('id');
— Миколай

9
Для чого це не потрібно використовувати jQuery, щоб отримати ідентифікатор - ще простіше використовувати чистий Javascript:document.activeElement.id
— Nick F

5
Зауважте, що на Сафарі це не працює так, як очікувалося. :(
— rinogo

@rinogo: що відбувається в Safari?
— Півмісяць Свіжий

1
У Safari document.activeElementце не вхід. У моєму випадку це модальний div (який містить форму).
— mgalgs

46

При подачі форми:

  • document.activeElement дасть вам кнопку натискання, яку натиснули.

  • document.activeElement.getAttribute('value') дасть вам значення цієї кнопки.


2
Зауважте, що на Сафарі це не працює так, як очікувалося. :(
— 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
@Tony, вибач, що раніше я не бачив твого питання. Ця відповідь цілком стосується форми подання. Кнопки надсилання теж натискають, і таким чином вони запускають подію натискання.
— Джонатан Каменіш

2
Поширення цієї відповіді над відповіддю мисливця, оскільки події подання форми запускаються перед будь-якими подіями натискання будь-якого дочірнього елемента. Це спричиняє труднощі, коли подія подання вашої форми скасовується return false, тоді як цей метод працює правильно, оскільки клацання пов'язане з формою замість її дочірніх.
— pospi

7
Це не вдається правильно обробити випадок, коли форма подається іншими способами, ніж клік (наприклад, натискання клавіші Enter). Коли форма подається за допомогою інших засобів, саме перша кнопка надсилання запустила подію надсилання, а не остання клацання.
— тихість

Після крапки є крапка з комою, ... $(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);
      });
    });

12

Я знайшов найкраще рішення

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

Це не тільки працює на входах, але також працює і на тегах кнопок. Також він отримує ідентифікатор кнопки.


Чорт, я маю побачити, чи моя сторінка працює на Safari зараз. Чому Сафарі завжди має бути таким важким. Дякую за це. Збираюся перевірити, коли я повернуся додому
— Томас Вільямс


Це не працює для мене в Safari. Клацніть слухача на кнопці в корпусі викликів. Підпишіть форму. Всередині $(document.activeElement).attr('id')повертається обробник відправкиundefined
— dyodji

7

Іншим можливим рішенням є додавання у форму прихованого поля:

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

Потім у функцію готовості додайте функції для запису натиснутої клавіші:

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

6

Спираючись на те, що зробили Стен і Янн-ч, але цей параметр за замовчуванням першої кнопки. Краса цього загального підходу полягає в тому, що він знімає як клавішу, так і клавішу введення (навіть якщо фокус був не на кнопці. Якщо вам потрібно дозволити ввести форму, тоді просто відповідайте на це, коли кнопка фокусується ( відповідь Стана) У моєму випадку я хотів дозволити ввести, щоб подати форму, навіть якщо поточний фокус користувача був на текстовому полі.

Я також використовував атрибут 'name', а не 'id', але це той самий підхід.

var pressedButtonName =
     typeof $(":input[type=submit]:focus")[0] === "undefined" ?
     $(":input[type=submit]:first")[0].name :
     $(":input[type=submit]:focus")[0].name;

Тож якщо ви переместите фокус на другу кнопку за допомогою TAB та натисніть RETURN, вона буде за замовчуванням на першу кнопку ...
— FrancescoMM


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

не погана ідея. Чи працює це для будь-якої кількості форм на сторінці?
— hawkexp

@hawk так, так і повинно. Я не знаю, чи є це бажаною поведінкою, але ваш код насправді не подає форму, тому і моя. Якщо ви хочете подати його, просто видаліть 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]');
})

Це справді має бути обрана відповідь. Я хотів би лише додати, що правило повинно бути"button,[type=submit]"
— Віл

@Якщо не всі кнопки є кнопками для надсилання, це залежить від їх типу.
— ptyskju

Так, але за відсутності <input type = "submit">], кожен UA, який я коли-небудь використовував, розглядав тег <button> як тригер подання форми, тому це спричинить цей випадок. Або автор може додати застереження, що всі елементи, здатні до подання, повинні мати властивості [type = submit] ... один з іншого.
— Віль

3
$("form input[type=submit]").click(function() {
    $("<input />")
        .attr('type', 'hidden')
        .attr('name', $(this).attr('name'))
        .attr('value', $(this).attr('value'))
    .appendTo(this)
});

додати приховане поле


Не працює в Firefox 30 / Windows 7. Примітка: у Firefox зараз потрібне приховане поле, оскільки воно може не надсилати натиснуте значення подання, якщо надсилається разом із jquery's: this.submit () у події під час подання. Мене трохи хвилює, що $ (this) .attr ("ім'я") може працювати не в усіх браузерах.
— користувач1610743

У мене 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.


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>



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>


Далі, У випадку події клацання кнопки у формі додайте до класу клас 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" (id вашої кнопки) при відправці. Це працює, якщо onClick виникає перед відправкою (?), В чому я не впевнений, чи завжди це правда.


0

Простий спосіб відрізнити, який натискається кнопка <або кнопка введення = "кнопка" ...>, перевіривши їх "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>

CSS DUMB:

input {display:block}

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"));


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

ви отримаєте сповіщення про те, що "елемент, на який натиснули, був мій кнопкою.

У вдосконаленому прикладі ви можете додати window.event.srcElement в process_form_submission, і ви матимете посилання на той елемент, який викликав процес.


1
не використовуйте onclick для елементів, це застаріло
— Krzysztof Cygan

1
Схоже, це не працює для кнопок подання, window.event.srcElement повертає ідентифікатор форми.
— 333 МГц

@KrzysztofCygan У вас є джерело цього?
— vard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.