Friday, June 1, 2012

JavaScript post request like a form submit


I'm trying to direct a browser to a different page. If I wanted a GET request, I might say




document.location.href = 'http://example.com/q=a';



But the resource I'm trying to access won't respond properly unless I use a POST request. If this were not dynamically generated, I might use the HTML




<form action="http://example.com/" method="POST">
<input type="hidden" name="q" value="a">
</form>



Then I would just submit the form from the DOM.



But really I would like JavaScript code that allows me to say




post_to_url('http://example.com/', {'q':'a'});



What's the best cross browser implementation?



Edit



I'm sorry I was not clear. I need a solution that changes the location of the browser, just like submitting a form. If this is possible with XMLHttpRequest , it is not obvious. And this should not be asynchronous, nor use XML, so Ajax is not the answer.


Source: Tips4all

11 comments:

  1. function post_to_url(path, params, method) {
    method = method || "post"; // Set method to post by default, if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
    if(params.hasOwnProperty(key)) {
    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("type", "hidden");
    hiddenField.setAttribute("name", key);
    hiddenField.setAttribute("value", params[key]);

    form.appendChild(hiddenField);
    }
    }

    document.body.appendChild(form);
    form.submit();
    }


    EDIT: Since this has gotten upvoted so much, I'm guessing people will be copy-pasting this a lot. So I added the hasOwnProperty check to fix any inadvertent bugs.

    ReplyDelete
  2. Using the createElement function provided in this answer, which is necessary due to IE's brokenness with the name attribute on elements created normally with document.createElement:

    function postToURL(url, values) {
    values = values || {};

    var form = createElement("form", {action: url,
    method: "POST",
    style: "display: none"});
    for (var property in values) {
    if (values.hasOwnProperty(property)) {
    var value = values[property];
    if (value instanceof Array) {
    for (var i = 0, l = value.length; i < l; i++) {
    form.appendChild(createElement("input", {type: "hidden",
    name: property,
    value: value[i]}));
    }
    }
    else {
    form.appendChild(createElement("input", {type: "hidden",
    name: property,
    value: value}));
    }
    }
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
    }

    ReplyDelete
  3. If you have Prototype installed, you can tighten up the code to generate and submit the hidden form like this:

    var form = new Element('form',
    {method: 'post', action: 'http://example.com/'});
    form.insert(new Element('input',
    {name: 'q', value: 'a', type: 'hidden'}));
    $(document.body).insert(form);
    form.submit();

    ReplyDelete
  4. A simple quick-and-dirty implementation of @Aaron answer:

    document.body.innerHTML += '<form id="dynForm" action="http://example.com/" method="post"><input type="hidden" name="q" value="a"></form>';
    document.getElementById("dynForm").submit();


    Of course, you should rather use a JavaScript framework such as Prototype or jQuery...

    ReplyDelete
  5. You can dynamically create a form, and then post that.

    ReplyDelete
  6. Rakesh Pai's answer is amazing, but there is an issue that occurs for me (in Safari) when you try to post a form with a field called submit. For example, post_to_url("http://google.com/",{ submit: "submit" } );. I have patched the function slightly to walk around this variable space collision.

    function post_to_url(path, params, method) {
    method = method || "post";

    var form = document.createElement("form");

    //Move the submit function to another variable
    //so that it doesn't get overwritten.
    form._submit_function_ = form.submit;

    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("type", "hidden");
    hiddenField.setAttribute("name", key);
    hiddenField.setAttribute("value", params[key]);

    form.appendChild(hiddenField);
    }

    document.body.appendChild(form);
    form._submit_function_(); //Call the renamed function.
    }
    post_to_url("http://google.com/", { submit: "submit" } ); //Works!

    ReplyDelete
  7. Three options here.


    Standard JavaScript answer: Use a framework! Most Ajax frameworks will have abstracted you an easy way to make an XMLHTTPRequest POST.
    Make the XMLHTTPRequest request yourself, passing post into the open method instead of get. (More information in Using POST method in XMLHTTPRequest (Ajax).)
    Via JavaScript, dynamically create a form, add an action, add your inputs, and submit that.

    ReplyDelete
  8. This would be a version of the selected answer using jQuery.

    // Post to the provided URL with the specified parameters.
    function post(path, parameters) {
    var form = $('<form></form>');

    form.attr("method", "post");
    form.attr("action", path);

    $.each(parameters, function(key, value) {
    var field = $('<input></input>');

    field.attr("type", "hidden");
    field.attr("name", key);
    field.attr("value", value);

    form.append(field);
    });

    // The form needs to be apart of the document in
    // order for us to be able to submit it.
    $(document.body).append(form);
    form.submit();
    }

    ReplyDelete
  9. One solution is to generate the form and submit it. One implementation is

    function post_to_url(url, params) {
    var form = document.createElement('form');
    form.action = url;
    form.method = 'POST';

    for (var i in params) {
    if (params.hasOwnProperty(i)) {
    var input = document.createElement('input');
    input.type = 'hidden';
    input.name = i;
    input.value = params[i];
    form.appendChild(input);
    }
    }

    form.submit();
    }


    So I can implement a URL shortening bookmarklet with a simple

    javascript:post_to_url('http://is.gd/create.php', {'URL': location.href});

    ReplyDelete
  10. Here is how I wrote it using jQuery. Tested in Firefox and Internet Explorer.

    function postToUrl(url, params, newWindow)
    {
    var form = $('<form>');
    form.attr('action', url);
    form.attr('method', 'POST');
    if(newWindow){ form.attr('target', '_blank'); }

    var addParam = function(paramName, paramValue){
    var input = $('<input type="hidden">');
    input.attr({ 'id': paramName,
    'name': paramName,
    'value': paramValue });
    form.append(input);
    };

    // Params is an Array.
    if(params instanceof Array){
    for(var i=0; i<params.length; i++){
    addParam(i, params[i]);
    }
    }

    // Params is an Associative array or Object.
    if(params instanceof Object){
    for(var key in params){
    addParam(key, params[key]);
    }
    }

    // Submit the form, then remove it from the page
    form.appendTo(document.body);
    form.submit();
    form.remove();
    }

    ReplyDelete
  11. You could dynamically add the form using DHTML and then submit.

    ReplyDelete