Determining which submit button was clicked from jQuery/JavaScript

14,359

Solution 1

See this question: Crossbrowser equivalent of explicitOriginalTarget event parameter

You're going to have to attach the event listeners to the buttons instead of the form to get a good reliable way of determining which one fired the submit.

Solution 2

Here is a function I used to "ajaxify" my forms with jQuery.

function ajaxifyForm(form, callback)
{
    var clicked

    form.find("button").click(function()
    {
        if (clicked != null) clicked.removeAttr("data-clicked")
        clicked = $(this)
        $(this).attr("data-clicked", 1)
    })

    form.submit(function(event)
    {
        var data = {}
        var name = ""

        form.find(":input").each(function()
        {
            var input = $(this)

            if (!(name = input.attr("name"))) return

            switch (input.attr("type"))
            {
                case "radio":
                case "checkbox":
                    if (input.attr("checked")) data[name] = input.val()
                    break
                case "submit":
                    if (input.attr("data-clicked")) data[name] = input.val()
                    break
                default:
                    data[name] = input.val()
            }
        })

        $.ajax({
            url: form.attr("action"),
            success: function(data)
            {
                if (typeof callback == "function") callback("success")
            },
            error: function()
            {
                if (typeof callback == "function") callback("error")
            },
            data: data,
            type: form.attr("method")
        })

        return false
    })

    return form
}

Solution 3

http://api.jquery.com/event.target/

jquery.event.target should work because it is normalised for most browsers.

jquery.event.currentTarget can be used to retrieve the current item in the event bubbling chain.

Edit-- After some reflection and @greg's suggestion: I've posted a code snippet on jsfiddle.

Solution 4

Using click handlers to submit the form is problematic beacuse you cannot use submit event handlers for validation (which is the way pretty much any validator plugin does it). Also, when you are not using AJAX to post, disabling submit buttons can have weird effects in some browsers if done in the click event and not the submit event.

The way jQuery.Form solves this is to set up a click handler which stores the clicked button (and then clears it with a small timeout), and use the submit handler to actually send the form contents via AJAX.

Share:
14,359
clifgriffin
Author by

clifgriffin

Updated on June 03, 2022

Comments

  • clifgriffin
    clifgriffin about 2 years

    I'm ajaxifying some forms from a PHP application I didn't write. To do this, I came up with this clever solution:

    jQuery("form").submit(function(event) {
        // get some values from elements on the page:
        var the_form = jQuery(this);
        var data = the_form.serialize();
        var url = the_form.attr( 'action' );
        var button = event.originalEvent.explicitOriginalTarget;
    
        data = data + "&" + button.name + "=" + button.value;
    
        // Send the data using post and put the results in a div
        jQuery.post( url, data, function() {
            //Do something crazy
        });
    
        // stop form from submitting normally
        if (event.preventDefault) 
        { 
            event.preventDefault(); 
        } 
        else 
        {
            event.returnValue = false; 
        }
    });
    

    Which works perfectly. I went away rejoicing. The problem is, I inadvertently used a Mozilla/Gecko only property to determine which button was clicked. (event.originalEvent.explicitOriginalTarget) Which means this only works in Firefox. :-(

    All of this is necessary because the web app I'm augmenting relies on the button name/value being in the post data to process the form correctly. So, my question in simple terms would be:

    What is the best, cross-browser way to determine which button was clicked in jQuery's submit event?

    Edit: And here is my solution.

    jQuery("some selector that targets your form").find(":submit").click(function(event) {
        // get some values from elements on the page:
        var the_form = jQuery(this).parents("form");
        var data = the_form.serialize();
        var url = the_form.attr( 'action' );
        var button = event.target;
    
        data = data + "&" + button.name + "=" + button.value;
    
        // Send the data using post and put the results in a div
        jQuery.post( url, data, function() {
            //Do something crazy
        });
    
        // stop form from submitting normally
        if (event.preventDefault) 
        { 
            event.preventDefault(); 
        } 
        else 
        {
            event.returnValue = false; 
        }
    });
    
  • clifgriffin
    clifgriffin about 13 years
    event.target is the form...not the button that triggered the submit.
  • clifgriffin
    clifgriffin about 13 years
    (and event.target.currentTarget is undefined. event.currentTarget is also the form)
  • leon
    leon about 13 years
    I see I overlooked the event listner- I was assuming you were listening on the button and then submitting the form- my bad. As @greg mention, think it would even read better to listen on the button click.
  • clifgriffin
    clifgriffin about 13 years
    Thanks for the feedback, Greg...I thought about switching to this method, but it just feels messy to me. I'd rather not try to predict every element that could cause a form submit and attach an event to it if I don't have to. Just seems like something jQuery/JavaScript/browsers should support.
  • greggreg
    greggreg about 13 years
    Well, the outcome you're getting is what the functionality should be. You're asking for an event triggered by the form, not an event triggered by the button. The form listens for the button's event and then fires it's own. The proper thing to do in this case, would be to have the buttons fire an event, then for you to intercept that event and trigger the form.
  • clifgriffin
    clifgriffin about 13 years
    Fine, I agree...you're right. Thanks ;)