Як я можу отримати кнопку, яка викликала надсилання від події надсилання форми?


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)
Болдевін

1
Це має бути відповіддю.
Рой Намір

2
Гммм ... це працює, якщо форма подається через [Enter]? Spec каже, що це має бути рівнозначним натисканню кнопки подання за замовчуванням, але я не впевнений, залишає її як активний елемент чи ні.
Зробіть

8
На жаль, ви не можете розраховувати лише на цеactiveElement , тому що "відправника" можна визначити: А. Через автентичну активацію клацання (натискають безпосередньо мишкою або клавіатурою Пробіл / Введення); B. Через синтетичну активацію клацання ( buttonElement.click()або buttonElement.dispatch(new MouseEvent(...))без уваги); C. за допомогою форми неявного подання (взаємодія клавіатури з полем іншої форми) D. нікому, колиformElement.submit()
пам’яті

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
Не може працювати перехресний переглядач / декілька кнопок подання.
користувач1610743

2
Чи гарантується, що подія натискання запускається перед подією надсилання форми? Я б запропонував дати формі doNotSubmitклас, всередині перевірити функцію подання, якщо клас не існує (інакше не подати), всередині події клацання видаліть клас форми doNotSubmitта зробіть тригер $ (''. MyForm '). ('подати'); після додавання значення кнопки подання як прихованого поля
Hafenkranich

2
@Hafenkranich У деяких рідкісних випадках на Chrome подія натискання запускається ПІСЛЯ події надсилання.
romanoza

@roamnoza саме з цим я і стикався.
Хафенкраніч

2
@ j4k3 Отримаєте краще рішення? Цій відповіді 8 років
мисливець

10

Я створив тестову форму і за допомогою Firebug знайшов такий спосіб отримати значення;

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

На жаль, лише Firefox підтримує цю подію.


5
IE не має цього властивості (
явноOriginalTarget

1
Старий добрий IE зіпсував його, пройшов Firebug і не міг бачити ніяких інших значень об'єкта, але просто забув про альтернативні браузери. Не дивно, що це не значить, доведеться перевірити Chrome.
Дейв Андерсон

11
Лише Firefox підтримує цю подію.
Енді Е

Отже, в HTML є щось, чого неможливо зробити в JS ... Mozilla вирішила реалізувати пропущену функцію, і ніхто не стежив за цим? Ось чому ми не можемо мати приємні речі
aross

6

Ось підхід, який видається більш чистим для моїх цілей.

По-перше, для будь-якої форми:

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

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

Потім у $ ('формі'). Submit () ви можете запитати, що було останнім клацанням, чимось подібним

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

6

Зараз 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);
}();

4

Відповідно до цього посилання , об’єкт події містить поле Event.target, яке:

Повертає рядок, що представляє об'єкт, який ініціював подію.

Я щойно створив сторінку, перевіряючи, що це за значення, і здається, що це представлення для самої форми, а не для натиснутої кнопки. Іншими словами, Javascript не забезпечує можливість визначати натиснуту кнопку.

Що стосується рішення Дейва Андерсона , то, можливо, було б корисно перевірити це в декількох браузерах, перш ніж використовувати його. Можливо, це могло б справно працювати, але я не можу сказати ні в якому разі.


1
targetПовертає всю форму. Таким чином, на жаль, не корисно виявити правильну кнопку подання.
Хафенкраніч

Я так багато говорю у своїй відповіді, @Hafenkranich.
cmptrgeekken

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: ні, це не так. У будь-якому випадку, кожен розробник може адаптувати рішення до власних потреб.
Дж. Бруні

jsfiddle.net/binki/d8ecv показує, що я маю на увазі щодо nameатрибута. Якщо форма повторно використовується і містить вхідні дані з різними іменами, старі введення можуть захаращувати форму.
бінкі

Тепер я бачу ... я оновлю свою відповідь. (Насправді я не приділяв великої уваги вашому коментарю через незв’язаний факт, що ви згадуєте <button/>елемент, в той час як <input type="submit" />він використовується в коді ...)
J. Bruni

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>

"поступається" ?, працює, не працює, корисно, не корисно, ...? , Я не розмовляю добре англійською
andres descalzo

@hunter, як я оскаржую ваш коментар кілька разів?
Том Оже

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"));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.