Changing the action of a form with JavaScript/jQuery

205,423

Solution 1

jQuery (1.4.2) gets confused if you have any form elements named "action". You can get around this by using the DOM attribute methods or simply avoid having form elements named "action".

<form action="foo">
  <button name="action" value="bar">Go</button>
</form>

<script type="text/javascript">
  $('form').attr('action', 'baz'); //this fails silently
  $('form').get(0).setAttribute('action', 'baz'); //this works
</script>

Solution 2

I agree with Paolo that we need to see more code. I tested this overly simplified example and it worked. This means that it is able to change the form action on the fly.

<script type="text/javascript">
function submitForm(){
    var form_url = $("#openid_form").attr("action");
    alert("Before - action=" + form_url);   
    //changing the action to google.com
    $("#openid_form").attr("action","http://google.com");
    alert("After - action = "+$("#openid_form").attr("action"));
    //submit the form
    $("#openid_form").submit();
}
</script>


<form id="openid_form" action="test.html">
    First Name:<input type="text" name="fname" /><br/>
    Last Name: <input type="text" name="lname" /><br/>
    <input type="button" onclick="submitForm()" value="Submit Form" />
</form>

EDIT: I tested the updated code you posted and found a syntax error in the declaration of providers_large. There's an extra comma. Firefox ignores the issue, but IE8 throws an error.

var providers_large = {
    google: {
        name: 'Google',
        url: 'https://www.google.com/accounts/o8/id'
    },
    facebook: {
        name: 'Facebook',
        form_url: 'http://wikipediamaze.rpxnow.com/facebook/start?token_url=http://www.wikipediamaze.com/Accounts/Logon'
    },  //<-- Here's the problem. Remove that comma

};

Solution 3

just to add a detail to what Tamlyn wrote, instead of
$('form').get(0).setAttribute('action', 'baz'); //this works

$('form')[0].setAttribute('action', 'baz');
works equally well

Solution 4

You can actually just use

$("#form").attr("target", "NewAction");

As far as I know, this will NOT fail silently.

If the page is opening in a new target, you may need to make sure the URL is unique each time because Webkit (chrome/safari) will cache the fact you have visited that URL and won't perform the post.

For example

$("form").attr("action", "/Pages/GeneratePreview?" + new Date().getMilliseconds());

Solution 5

Just an update to this - I've been having a similar problem updating the action attribute of a form with jQuery.

After some testing it turns out that the command: $('#myForm').attr('action','new_url.html');

silently fails if the action attribute of the form is empty. If i update the action attribute of my form to contain some text, the jquery works.

Share:
205,423
Micah
Author by

Micah

Updated on July 08, 2022

Comments

  • Micah
    Micah almost 2 years

    I'm having an issue that is driving me crazy. I'm trying to modify the openid-selector to support facebook. I'm using RPXNow as my provider so it requires the form to be submitted to a different url than the standard.

    For example. RpxNow requires me to setup my form like this:

    <form action="https://wikipediamaze.rpxnow.com/openid/start?token_url=...">

    This works for every provider except for Facebook and Myspace. Those require the form to be posted to a different url like this:

    <form action="https://wikipediamaze.rpxnow.com/facebook/start?token_url=...">

    and

    <form action="https://wikipediamaze.rpxnow.com/myspace/start?token_url=...">

    The open id selector has a bunch of buttons on the form each representing the openid providers. What I'm trying to do is detect when the Facebook or Myspace button is clicked and changed the action on the form before submitting. However it's not working. Here is my code.

    I've tried several variations all with the same "not supported" exception

    $("#openid_form").attr("action", form_url)
    document.forms[0].action = form_url
    

    Any suggestions?

    Update

    Here are more details on the code. I've omitted some for brevity. The only thing i've done is added the Facebook section to the "providers_large" object (which successfully adds the logo to the website), and instead of supply a url identifying the user, I'm creating a property called "form_url" which is what I want to set the action of my form to. If you look at the section title "Provider image click" you'll see where I'm checking for the presence of the property "form_url" and using jQuery to change the action and submit the form. However when I step through the JavaScript in debug mode it tells me it's an invalid operation.

    var providers_large = {
        google: {
            name: 'Google',
            url: 'https://www.google.com/accounts/o8/id'
        },
        facebook: {
            name: 'Facebook',
            form_url: 'http://wikipediamaze.rpxnow.com/facebook/start?token_url=http://www.wikipediamaze.com/Accounts/Logon'
        },
    
    };
    var providers_small = {
        myopenid: {
            name: 'MyOpenID',
            label: 'Enter your MyOpenID username.',
            url: 'http://{username}.myopenid.com/'
        },
        livejournal: {
            name: 'LiveJournal',
            label: 'Enter your Livejournal username.',
            url: 'http://{username}.livejournal.com/'
        },
        flickr: {
            name: 'Flickr',        
            label: 'Enter your Flickr username.',
            url: 'http://flickr.com/{username}/'
        },
        technorati: {
            name: 'Technorati',
            label: 'Enter your Technorati username.',
            url: 'http://technorati.com/people/technorati/{username}/'
        },
        wordpress: {
            name: 'Wordpress',
            label: 'Enter your Wordpress.com username.',
            url: 'http://{username}.wordpress.com/'
        },
        blogger: {
            name: 'Blogger',
            label: 'Your Blogger account',
            url: 'http://{username}.blogspot.com/'
        },
        verisign: {
            name: 'Verisign',
            label: 'Your Verisign username',
            url: 'http://{username}.pip.verisignlabs.com/'
        },
        vidoop: {
            name: 'Vidoop',
            label: 'Your Vidoop username',
            url: 'http://{username}.myvidoop.com/'
        },
        verisign: {
            name: 'Verisign',
            label: 'Your Verisign username',
            url: 'http://{username}.pip.verisignlabs.com/'
        },
        claimid: {
            name: 'ClaimID',
            label: 'Your ClaimID username',
            url: 'http://claimid.com/{username}'
        }
    };
    var providers = $.extend({}, providers_large, providers_small);
    
    var openid = {
    
            cookie_expires: 6*30,   // 6 months.
            cookie_name: 'openid_provider',
            cookie_path: '/',
    
            img_path: 'images/',
    
            input_id: null,
            provider_url: null,
    
        init: function(input_id) {
    
            var openid_btns = $('#openid_btns');
    
            this.input_id = input_id;
    
            $('#openid_choice').show();
            $('#openid_input_area').empty();
    
            // add box for each provider
            for (id in providers_large) {
    
                    openid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif'));
            }
            if (providers_small) {
                    openid_btns.append('<br/>');
    
                    for (id in providers_small) {
    
                            openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico'));
                    }
            }
    
            $('#openid_form').submit(this.submit);
    
            var box_id = this.readCookie();
            if (box_id) {
                    this.signin(box_id, true);
            }  
        },
        getBoxHTML: function(provider, box_size, image_ext) {
    
            var box_id = provider["name"].toLowerCase();
            return '<a title="'+provider["name"]+'" href="javascript: openid.signin(\''+ box_id +'\');"' +
                            ' style="background: #FFF url(' + this.img_path + box_id + image_ext+') no-repeat center center" ' + 
                            'class="' + box_id + ' openid_' + box_size + '_btn"></a>';    
    
        },
        /* Provider image click */
        signin: function(box_id, onload) {
    
            var provider = providers[box_id];
                    if (! provider) {
                            return;
                    }
    
                    this.highlight(box_id);
                    this.setCookie(box_id);
    
                    // prompt user for input?
                    if (provider['label']) {
    
                            this.useInputBox(provider);
                            this.provider_url = provider['url'];
    
                    } 
                    else if(provider['form_url']) {
    
                            $('#openid_form').attr("action", provider['form_url']);
                            $('#openid_form').submit();
                    }
                    else {
    
                            this.setOpenIdUrl(provider['url']);
                            if (! onload) {
                                    $('#openid_form').submit();
                            }       
                    }
        },
        /* Sign-in button click */
        submit: function() {
    
            var url = openid.provider_url; 
            if (url) {
                    url = url.replace('{username}', $('#openid_username').val());
                    openid.setOpenIdUrl(url);
            }
            return true;
        },
        setOpenIdUrl: function (url) {
    
            var hidden = $('#'+this.input_id);
            if (hidden.length > 0) {
                    hidden.value = url;
            } else {
                    $('#openid_form').append('<input type="hidden" id="' + this.input_id + '" name="' + this.input_id + '" value="'+url+'"/>');
            }
        },
        highlight: function (box_id) {
    
            // remove previous highlight.
            var highlight = $('#openid_highlight');
            if (highlight) {
                    highlight.replaceWith($('#openid_highlight a')[0]);
            }
            // add new highlight.
            $('.'+box_id).wrap('<div id="openid_highlight"></div>');
        },
        setCookie: function (value) {
    
                    var date = new Date();
                    date.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000));
                    var expires = "; expires="+date.toGMTString();
    
                    document.cookie = this.cookie_name+"="+value+expires+"; path=" + this.cookie_path;
        },
        readCookie: function () {
                    var nameEQ = this.cookie_name + "=";
                    var ca = document.cookie.split(';');
                    for(var i=0;i < ca.length;i++) {
                            var c = ca[i];
                            while (c.charAt(0)==' ') c = c.substring(1,c.length);
                            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
                    }
                    return null;
        },
        useInputBox: function (provider) {
    
                    var input_area = $('#openid_input_area');
    
                    var html = '';
                    var id = 'openid_username';
                    var value = '';
                    var label = provider['label'];
                    var style = '';
    
                    if (label) {
                            html = '<p>' + label + '</p>';
                    }
                    if (provider['name'] == 'OpenID') {
                            id = this.input_id;
                            value = 'http://';
                            style = 'background:#FFF url('+this.img_path+'openid-inputicon.gif) no-repeat scroll 0 50%; padding-left:18px;';
                    }
                    html += '<input id="'+id+'" type="text" style="'+style+'" name="'+id+'" value="'+value+'" />' + 
                                            '<input id="openid_submit" type="submit" value="Sign-In"/>';
    
                    input_area.empty();
                    input_area.append(html);
    
                    $('#'+id).focus();
        }
    };
    
  • Jose Basilio
    Jose Basilio almost 15 years
    Yes. I tested in IE8, FF and Chrome.
  • Micah
    Micah almost 15 years
    That's a type on my part when I put the code in to stackoverflow. There are a bunch of other providers_larg declarations that I removed for brevity. If you have the time, maybe download the library from code.google.com/p/openid-selector and see if you can get to work. It's one of those issues that have been riving me crazy and I don't have the brain capacity at the moment to figure it out. I really appreciate the help.
  • Micah
    Micah almost 15 years
    I modified the code slightly. Check it out at www.wikipediamaze.com/account/login. It works fine in Chrome but none of the other browsers.
  • ebt
    ebt over 13 years
    thanks, this helped me out tremendously. I found this while I had some hair left, whew.
  • Ardee Aram
    Ardee Aram over 13 years
    I have this scenario as well, but mine is more treacherous. I just used the Wordpress settings_field() function, only to find out that the function outputs an <input name="action" value="update" /> in it. Thank you so much for this.
  • Anon
    Anon about 13 years
    Ah ha! You just saved me! Form field named action screwing it up for me.
  • Polsonby
    Polsonby almost 13 years
    FWIW, bit off topic perhaps, but form fields called action also screw up if you're using Zend MVC - it silently sets a field called action as part of the routing and they stomp all over each other. You'd think after the first few times I'd remember but it still gets me from time to time
  • Admin
    Admin over 12 years
    Worked for me using $($(myform).get(0)).attr('action', action);
  • Ian Stanway
    Ian Stanway about 12 years
    Quite right, plus the method needs to be stated too. Thanks for the reminder, I feel like an idiot now ;-)
  • neobie
    neobie over 11 years
    jquery 1.8, still same problem :(