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.