JavaScript post request like a form submit - javascript

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?
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.

Dynamically create <input>s in a form and submit it
/**
* sends a request to the specified url from a form. this will change the window location.
* #param {string} path the path to send the post request to
* #param {object} params the parameters to add to the url
* #param {string} [method=post] the method to use on the form
*/
function post(path, params, method='post') {
// The rest of this code assumes you are not using a library.
// It can be made less verbose if you use one.
const form = document.createElement('form');
form.method = method;
form.action = path;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
Example:
post('/contact/', {name: 'Johnny Bravo'});
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.

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 a part of the document in
// order for us to be able to submit it.
$(document.body).append(form);
form.submit();
}

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...

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);
}

Rakesh Pai's answer is amazing, but there is an issue that occurs for me (in Safari) when I 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!

No. You can't have the JavaScript post request like a form submit.
What you can have is a form in HTML, then submit it with the JavaScript. (as explained many times on this page).
You can create the HTML yourself, you don't need JavaScript to write the HTML. That would be silly if people suggested that.
<form id="ninja" action="http://example.com/" method="POST">
<input id="donaldduck" type="hidden" name="q" value="a">
</form>
Your function would just configure the form the way you want it.
function postToURL(a,b,c){
document.getElementById("ninja").action = a;
document.getElementById("donaldduck").name = b;
document.getElementById("donaldduck").value = c;
document.getElementById("ninja").submit();
}
Then, use it like.
postToURL("http://example.com/","q","a");
But I would just leave out the function and just do.
document.getElementById('donaldduck').value = "a";
document.getElementById("ninja").submit();
Finally, the style decision goes in the ccs file.
#ninja {
display: none;
}
Personally I think forms should be addressed by name but that is not important right now.

this is the answer of rakesh, but with support for arrays (which is quite common in forms):
plain javascript:
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);
var addField = function( key, value ){
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value );
form.appendChild(hiddenField);
};
for(var key in params) {
if(params.hasOwnProperty(key)) {
if( params[key] instanceof Array ){
for(var i = 0; i < params[key].length; i++){
addField( key, params[key][i] )
}
}
else{
addField( key, params[key] );
}
}
}
document.body.appendChild(form);
form.submit();
}
oh, and here's the jquery version: (slightly different code, but boils down to the same thing)
function post_to_url(path, params, method) {
method = method || "post"; // Set method to post by default, if not specified.
var form = $(document.createElement( "form" ))
.attr( {"method": method, "action": path} );
$.each( params, function(key,value){
$.each( value instanceof Array? value : [value], function(i,val){
$(document.createElement("input"))
.attr({ "type": "hidden", "name": key, "value": val })
.appendTo( form );
});
} );
form.appendTo( document.body ).submit();
}

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();

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});

Well, wish I had read all the other posts so I didn't lose time creating this from Rakesh Pai's answer. Here's a recursive solution that works with arrays and objects. No dependency on jQuery.
Added a segment to handle cases where the entire form should be submitted like an array. (ie. where there's no wrapper object around a list of items)
/**
* Posts javascript data to a url using form.submit().
* Note: Handles json and arrays.
* #param {string} path - url where the data should be sent.
* #param {string} data - data as javascript object (JSON).
* #param {object} options -- optional attributes
* {
* {string} method: get/post/put/etc,
* {string} arrayName: name to post arraylike data. Only necessary when root data object is an array.
* }
* #example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
*/
function postToUrl(path, data, options) {
if (options === undefined) {
options = {};
}
var method = options.method || "post"; // Set method to post by default if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
function constructElements(item, parentString) {
for (var key in item) {
if (item.hasOwnProperty(key) && item[key] != null) {
if (Object.prototype.toString.call(item[key]) === '[object Array]') {
for (var i = 0; i < item[key].length; i++) {
constructElements(item[key][i], parentString + key + "[" + i + "].");
}
} else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
constructElements(item[key], parentString + key + ".");
} else {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", parentString + key);
hiddenField.setAttribute("value", item[key]);
form.appendChild(hiddenField);
}
}
}
}
//if the parent 'data' object is an array we need to treat it a little differently
if (Object.prototype.toString.call(data) === '[object Array]') {
if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
//loop through each array item at the parent level
for (var i = 0; i < data.length; i++) {
constructElements(data[i], (options.arrayName || "") + "[" + i + "].");
}
} else {
//otherwise treat it normally
constructElements(data, "");
}
document.body.appendChild(form);
form.submit();
};

I'd go down the Ajax route as others suggested with something like:
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open("POST", "YourPageHere.asp", true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
self.xmlHttpReq.setRequestHeader("Content-length", QueryString.length);
self.xmlHttpReq.send("?YourQueryString=Value");

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.

The easiest way is using Ajax Post Request:
$.ajax({
type: "POST",
url: 'http://www.myrestserver.com/api',
data: data,
success: success,
dataType: dataType
});
where:
data is an object
dataType is the data expected by the server (xml,
json, script, text, html)
url is the address of your RESt server or any function on the server side that accept the HTTP-POST.
Then in the success handler redirect the browser with something like window.location.

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();
}

The Prototype library includes a Hashtable object, with a ".toQueryString()" method, which allows you to easily turn a JavaScript object/structure into a query-string style string. Since the post requires the "body" of the request to be a query-string formatted string, this allows your Ajax request to work properly as a post. Here's an example using Prototype:
$req = new Ajax.Request("http://foo.com/bar.php",{
method: 'post',
parameters: $H({
name: 'Diodeus',
question: 'JavaScript posts a request like a form request',
...
}).toQueryString();
};

This works perfectly in my case:
document.getElementById("form1").submit();
You can use it in function like:
function formSubmit() {
document.getElementById("frmUserList").submit();
}
Using this you can post all the values of inputs.

My solution will encode deeply nested objects, unlike the currently accepted solution by #RakeshPai.
It uses the 'qs' npm library and its stringify function to convert nested objects into parameters.
This code works well with a Rails back-end, although you should be able to modify it to work with whatever backend you need by modifying the options passed to stringify. Rails requires that arrayFormat be set to "brackets".
import qs from "qs"
function normalPost(url, params) {
var form = document.createElement("form");
form.setAttribute("method", "POST");
form.setAttribute("action", url);
const keyValues = qs
.stringify(params, { arrayFormat: "brackets", encode: false })
.split("&")
.map(field => field.split("="));
keyValues.forEach(field => {
var key = field[0];
var value = field[1];
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", value);
form.appendChild(hiddenField);
});
document.body.appendChild(form);
form.submit();
}
Example:
normalPost("/people/new", {
people: [
{
name: "Chris",
address: "My address",
dogs: ["Jordan", "Elephant Man", "Chicken Face"],
information: { age: 10, height: "3 meters" }
},
{
name: "Andrew",
address: "Underworld",
dogs: ["Doug", "Elf", "Orange"]
},
{
name: "Julian",
address: "In a hole",
dogs: ["Please", "Help"]
}
]
});
Produces these Rails parameters:
{"authenticity_token"=>"...",
"people"=>
[{"name"=>"Chris", "address"=>"My address", "dogs"=>["Jordan", "Elephant Man", "Chicken Face"], "information"=>{"age"=>"10", "height"=>"3 meters"}},
{"name"=>"Andrew", "address"=>"Underworld", "dogs"=>["Doug", "Elf", "Orange"]},
{"name"=>"Julian", "address"=>"In a hole", "dogs"=>["Please", "Help"]}]}

Yet another recursive solution, since some of others seem to be broken (I didn't test all of them). This one depends on lodash 3.x and ES6 (jQuery not required):
function createHiddenInput(name, value) {
let input = document.createElement('input');
input.setAttribute('type','hidden');
input.setAttribute('name',name);
input.setAttribute('value',value);
return input;
}
function appendInput(form, name, value) {
if(_.isArray(value)) {
_.each(value, (v,i) => {
appendInput(form, `${name}[${i}]`, v);
});
} else if(_.isObject(value)) {
_.forOwn(value, (v,p) => {
appendInput(form, `${name}[${p}]`, v);
});
} else {
form.appendChild(createHiddenInput(name, value));
}
}
function postToUrl(url, data) {
let form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', url);
_.forOwn(data, (value, name) => {
appendInput(form, name, value);
});
form.submit();
}

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

FormObject is an option. But FormObject is not supported by most browsers now.

This is like Alan's option 2 (above). How to instantiate the httpobj is left as an excercise.
httpobj.open("POST", url, true);
httpobj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
httpobj.onreadystatechange=handler;
httpobj.send(post);

This is based on beauSD's code using jQuery. It is improved so it works recursively on objects.
function post(url, params, urlEncoded, newWindow) {
var form = $('<form />').hide();
form.attr('action', url)
.attr('method', 'POST')
.attr('enctype', urlEncoded ? 'application/x-www-form-urlencoded' : 'multipart/form-data');
if(newWindow) form.attr('target', '_blank');
function addParam(name, value, parent) {
var fullname = (parent.length > 0 ? (parent + '[' + name + ']') : name);
if(value instanceof Object) {
for(var i in value) {
addParam(i, value[i], fullname);
}
}
else $('<input type="hidden" />').attr({name: fullname, value: value}).appendTo(form);
};
addParam('', params, '');
$('body').append(form);
form.submit();
}

The accepted answer will reload the page like a native form submit. This modified version, will submit through XHR:
function post(path, params) {
const form = document.createElement('form');
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
var button = form.ownerDocument.createElement('input');
button.type = 'submit';
form.appendChild(button);
form.onsubmit = async function (e) {
console.log('hi');
e.preventDefault();
const form = e.currentTarget;
try {
const formData = new FormData(form);
const response = await fetch(path, {
method: 'POST',
body: formData,
});
console.log(response);
} catch (error) {
console.error(error);
}
};
document.body.appendChild(form);
button.click();
}

I use the document.forms and loop it to get all the elements in the form, then send via XMLHttpRequest. So this is my solution for javascript / ajax submission (with all HTML included as an example):
function smc() {
var http = new XMLHttpRequest();
var url = "yourphpfile.php";
var x = document.forms[0];
var xstr = "";
var i;
for (i = 0; i < x.length; i++) {
if (i == 0) {
xstr += x.elements[i].name + "=" + x.elements[i].value;
} else {
xstr += "&" + x.elements[i].name + "=" + x.elements[i].value;
}
}
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
// do whatever you want to with the html output response here
}
}
http.send(xstr);
}
<!DOCTYPE html>
<html>
<body>
<form>
First name: <input type="text" name="fname" value="Donald"><br> Last name: <input type="text" name="lname" value="Duck"><br> Addr1: <input type="text" name="add" value="123 Pond Dr"><br> City: <input type="text" name="city" value="Duckopolis"><br>
</form>
<button onclick="smc()">Submit</button>
</body>
</html>

The method I use to post and direct a user automatically to another page is to just write a hidden form and then auto submit it. Be assured that the hidden form takes absolutely no space on the web page. The code would be something like this:
<form name="form1" method="post" action="somepage.php">
<input name="fielda" type="text" id="fielda" type="hidden">
<textarea name="fieldb" id="fieldb" cols="" rows="" style="display:none"></textarea>
</form>
document.getElementById('fielda').value="some text for field a";
document.getElementById('fieldb').innerHTML="some text for multiline fieldb";
form1.submit();
Application of auto submit
An application of an auto submit would be directing form values that the user automatically put in on the other page back to that page. Such an application would be like this:
fieldapost=<?php echo $_post['fielda'];>
if (fieldapost !="") {
document.write("<form name='form1' method='post' action='previouspage.php'>
<input name='fielda' type='text' id='fielda' type='hidden'>
</form>");
document.getElementById('fielda').value=fieldapost;
form1.submit();
}

Here is how I do it.
function redirectWithPost(url, data){
var form = document.createElement('form');
form.method = 'POST';
form.action = url;
for(var key in data){
var input = document.createElement('input');
input.name = key;
input.value = data[key];
input.type = 'hidden';
form.appendChild(input)
}
document.body.appendChild(form);
form.submit();
}

jQuery plugin for redirect with POST or GET:
https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
To test, include the above .js file or copy/paste the class into your code, then use the code here, replacing "args" with your variable names, and "values" with the values of those respective variables:
$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});

None of the above solutions handled deep nested params with just jQuery,
so here is my two cents solution.
If you're using jQuery and you need to handle deep nested parameters, you can use this function below:
/**
* Original code found here: https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
* I just simplified it for my own taste.
*/
function postForm(parameters, url) {
// generally we post the form with a blank action attribute
if ('undefined' === typeof url) {
url = '';
}
//----------------------------------------
// SOME HELPER FUNCTIONS
//----------------------------------------
var getForm = function (url, values) {
values = removeNulls(values);
var form = $('<form>')
.attr("method", 'POST')
.attr("action", url);
iterateValues(values, [], form, null);
return form;
};
var removeNulls = function (values) {
var propNames = Object.getOwnPropertyNames(values);
for (var i = 0; i < propNames.length; i++) {
var propName = propNames[i];
if (values[propName] === null || values[propName] === undefined) {
delete values[propName];
} else if (typeof values[propName] === 'object') {
values[propName] = removeNulls(values[propName]);
} else if (values[propName].length < 1) {
delete values[propName];
}
}
return values;
};
var iterateValues = function (values, parent, form, isArray) {
var i, iterateParent = [];
Object.keys(values).forEach(function (i) {
if (typeof values[i] === "object") {
iterateParent = parent.slice();
iterateParent.push(i);
iterateValues(values[i], iterateParent, form, Array.isArray(values[i]));
} else {
form.append(getInput(i, values[i], parent, isArray));
}
});
};
var getInput = function (name, value, parent, array) {
var parentString;
if (parent.length > 0) {
parentString = parent[0];
var i;
for (i = 1; i < parent.length; i += 1) {
parentString += "[" + parent[i] + "]";
}
if (array) {
name = parentString + "[" + name + "]";
} else {
name = parentString + "[" + name + "]";
}
}
return $("<input>").attr("type", "hidden")
.attr("name", name)
.attr("value", value);
};
//----------------------------------------
// NOW THE SYNOPSIS
//----------------------------------------
var generatedForm = getForm(url, parameters);
$('body').append(generatedForm);
generatedForm.submit();
generatedForm.remove();
}
Here is an example of how to use it.
The html code:
<button id="testButton">Button</button>
<script>
$(document).ready(function () {
$("#testButton").click(function () {
postForm({
csrf_token: "abcd",
rows: [
{
user_id: 1,
permission_group_id: 1
},
{
user_id: 1,
permission_group_id: 2
}
],
object: {
apple: {
color: "red",
age: "23 days",
types: [
"golden",
"opal",
]
}
},
the_null: null, // this will be dropped, like non-checked checkboxes are dropped
});
});
});
</script>
And if you click the test button, it will post the form and you will get the following values in POST:
array(3) {
["csrf_token"] => string(4) "abcd"
["rows"] => array(2) {
[0] => array(2) {
["user_id"] => string(1) "1"
["permission_group_id"] => string(1) "1"
}
[1] => array(2) {
["user_id"] => string(1) "1"
["permission_group_id"] => string(1) "2"
}
}
["object"] => array(1) {
["apple"] => array(3) {
["color"] => string(3) "red"
["age"] => string(7) "23 days"
["types"] => array(2) {
[0] => string(6) "golden"
[1] => string(4) "opal"
}
}
}
}
Note: if you want to post the form to another url than the current page, you can specify the url as the second argument of the postForm function.
So for instance (to re-use your example):
postForm({'q':'a'}, 'http://example.com/');
Hope this helps.
Note2: the code was taken from the redirect plugin. I basically just simplified it
for my needs.

You could use jQuery's trigger method to submit the form, just like you press a button, like so,
$('form').trigger('submit')
it will submit on the browser.

Try
function post_to_url(url, obj) {
let id=`form_${+new Date()}`;
document.body.innerHTML+=`
<form id="${id}" action="${url}" method="POST">
${Object.keys(obj).map(k=>`
<input type="hidden" name="${k}" value="${obj[k]}">
`)}
</form>`
this[id].submit();
}
// TEST - in second param object can have more keys
function jump() { post_to_url('https://example.com/', {'q':'a'}); }
Open chrome>networks and push button:
<button onclick="jump()">Send POST</button>

Related

How can I conditionally allow or prevent submission execution?

The situation
I have a page in which I have multiple forms keeping track of the attendance and one progress_update.
On submit of the progress_update form I have got it so that ajax sends the attendance form submissions separately having used the preventdefault() method to stop the original submission, however I would like to on the condition that no errors were returned by the ajax methods allow the original submission that was originally prevented.
What I have so far:
The ajax function:
function send_attendance(name, lesson, form_id, i) {
var url = '/attendance/' + name + '/' + lesson
$('#error-' + i).hide('slow')
$('#error-' + i).html('')
$.ajax({
type: "POST",
url: url,
data: {
attended: $('#attended' + i).val(),
score: $('#score' + i).val(),
writing: $('#writing' + i).val(),
speaking: $('#speaking' + i).val()},
success: function(data) {
if (data.data.message == undefined) {
allow=false;
if (data.data.score[1] == undefined) {
var error_data = data.data.score[0]
} else {
var error_data = data.data.score[1]
}
$('#error-' + i).show('slow')
$('#error-' + i).html('<p style="color:red;">' + error_data + '</p>')
} else {
console.log(data.data.message) // display the returned data in the console.
}
}
});
}
The Intention:
The intention behind this ajax is to send the forms to a separate route for validation and then on success "receiving data.data.message == 'submitted'" pass to the next form in the loop, while on error set the allow variable to false and display the message in hopes to prevent the final form being submitted at the same time.
The call:
$('#update_form').submit(function (e) {
var allow = true;
for (var i = 0; i < studentcount ; i++) {
send_attendance(name=st[i], lesson=lesson, form_id='attendance-' + i, i=i)
}
if (allow == true){
} else {
e.preventDefault();
}
});
The Problem
In doing what I have done I have ended up with a situation of it either submits the ajax submitted forms and that is that preventing the submit form or it submits the form whether errors occured in the ajax that need to be displayed, now how do I get this to work in the way expected? I have tried the methods involved in these previous questions:
How to reenable event.preventDefault?
How to unbind a listener that is calling event.preventDefault() (using jQuery)?
which revolve around using bind and unbind but this doesn't seem to work as needed and results in a similar error.
Any advice would be greatly appreciated.
Edit:
I have adjusted the code based on the comment below to reflect, however it still seems to be evaluating the allow before the ajax have completed. either that or the ajax function isn't changing the allow variable which is set in the submit() call how could i get this to change the allow and evaluate it after the ajax calls are complete?
The Ajax call
function send_attendance(name, lesson, form_id, i) {
var url = '/attendance/' + name + '/' + lesson
$('#error-' + i).hide('slow')
$('#error-' + i).html('')
var form = $('#' + form_id)
$.ajax({
type: "POST",
url: url,
data: $('#'+ form_id).serialize(),
context: form,
success: function(data) {
console.log('done')
if (data.data.message == undefined) {
allow = false;
if (data.data.score[1] == undefined) {
var error_data = data.data.score[0]
} else {
var error_data = data.data.score[1]
}
$('#error-' + i).show('slow')
$('#error-' + i).html('<p style="color:red;">' + error_data + '</p>')
} else {
console.log(data.data.message) // display the returned data in the console.
}
}
});
The function is being called here:
$('#update_form').submit(function (e) {
e.preventDefault();
var allow = true;
var deferreds = [];
for (var i = 0; i < studentcount ; i++) {
deferreds.push(
send_attendance(st[i], lesson, 'attendance-' + i, i));
}
$.when(...deferreds).then(function() {
if (allow == true){
console.log('True')
} else {
console.log('False')
}
});
I also tried:
$('#update_form').submit(function (e) {
e.preventDefault();
var allow = true;
var deferreds = [];
for (var i = 0; i < studentcount ; i++) {
deferreds.push(
send_attendance(st[i], lesson, 'attendance-' + i, i));
}
$.when.apply(deferreds).done(function() {
if (allow == true){
console.log('True')
} else {
console.log('False')
}
});

special character % is transmitted to % at server side through jquery AJAX call: Updated

I have a HTML form as the output of a java that gets a text from database and fill an input of that form with it. In form I can edit the text that on submit
Is sent back to java via a jquery AJAX call. Through java the text is saved in the database.
If I enter test% in text area it is coming as test% at server side.
Let’s say the HTML form looks like this :
<form id="form_used_0" action="#" method="post" onclick="hideAjaxList();">
<textarea name="summary" id=" summary " data-mini="true"><%=HtmlWriter.preformat(summary)%></textarea>
<a id="saveBtn" class="actionBtn" href="#" data-theme="b" onclick="onSave (this);">Save</a>
</form>
On saveBtn click this AJAX call is made:
function onSave(thisHref)
{
var respData = "";
var id = $("#id").attr("value");
var params = $("#form_used").serialize()+"&ajaxAction=SaveHeader"+"&id="+id;
$.post(ajaxURL, params, function(data){
if(data.length >0)
{
respData = data.substring(data.indexOf("|")+1, data.lastIndexOf("|"));
}
}).complete(function(){
if (respData.length > 0)
{
var responseData = respData.split("|");
var status = responseData[0];
var msg = responseData[1];
if (status == 'SUCCESS')
{
showSuccessMsgHeader(msg);
}
else if (status == 'ERROR')
{
showErrorMsgsOnly(msg);
}
}
});
}
I tried using the serializeArray method but now getting 400 Bad request error. I checked the form data in network tab and found that it is showing as unable to decode value beside input field .
function onSave(thisHref)
{
var respData = "";
var id = $("#id").attr("value");
var x = $("#form_used_0").serializeArray();
var paramsArr = "";
$.each(x, function(i, field){
if(i == x.length - 1){
paramsArr = paramsArr + field.name + "=" + field.value;
} else {
paramsArr = paramsArr + field.name + "=" + field.value + "&";
}
});
var params paramsArr +"&ajaxAction=SaveHeader"+"&id="+id;
$.post(ajaxURL, params, function(data){
if(data.length >0)
{
respData = data.substring(data.indexOf("|")+1, data.lastIndexOf("|"));
}
}).complete(function(){
if (respData.length > 0)
{
var responseData = respData.split("|");
var status = responseData[0];
var msg = responseData[1];
if (status == 'SUCCESS')
{
showSuccessMsgHeader(msg);
}
else if (status == 'ERROR')
{
showErrorMsgsOnly(msg);
}
}
});
}
Would it be possible for anyone to help me on the same.
As per jQuery documentation, The .serialize() method creates a text string in standard URL-encoded notation.
You can use Apache Commons StringEscapeUtils.unescapeHtml() to decode the string at server level.
Alternatively, if required you can pass the text from textarea as an additional param, which you can use it.
Thanks.

Add to cart button - Javascript/JQuery error

When webpage loads:
Invalid App Id: Must be a number or numeric string representing the application id.
When Add to Cart button is clicked:
Uncaught TypeError: Cannot read property 'id' of undefined - (index):459
Below is the Javascript, I have marked the area with "ERROR LINE" at (index):459
var productAddToCartForm = new VarienForm('product_addtocart_form');
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
if ($(button).id.indexOf('ec_shortcut') != -1) { // -ERROR LINE
try {
this.form.submit();
return;
} catch (e) {}
}
if (!url) {
url = jQuery('#product_addtocart_form').attr('action');
}
url = url.replace("checkout/cart", "oxajax/cart");
url = url.replace("wishlist/index/cart", "oxajax/cart/add");
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
if ('https:' == document.location.protocol) {
url = url.replace('http:', 'https:');
}
jQuery.fancybox.showActivity();
jQuery.ajax({
url: url,
dataType: 'jsonp',
type: 'post',
data: data,
success: function(data) {
Olegnax.Ajaxcart.helpers.showMessage(data.message);
Olegnax.Ajaxcart.helpers.cartSuccessFunc(data);
}
});
this.form.action = oldUrl;
if (e) {
throw e;
}
}
}.bind(productAddToCartForm);
$(button).id - Error Cause
$(button) is a jQuery object, use $(button)[0].id or $(button).prop('id') or just button.id
Assuming button is a DOMElement you can use:
if (button.id.indexOf('ec_shortcut') != -1) {
Alternatively, you can get the id property from the jQuery object using prop():
if ($(button).prop('id').indexOf('ec_shortcut') != -1) {
Try this: button.id.indexOf('ec_shortcut')
use attr to get the id value
$(button).attr('id');
NOTE: You can get any attribute value using this method
See jQuery Docs for more info

Javascript form only seems to submit properly to new tab, not same tab

I know the title is weird, but I can't think of a succinct way of saying this:
This code creates a form and submits to a URL:
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);
//form.setAttribute("target", "_blank");
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();
}
As you can see, I've commented out the target attribute.
I have the following code that calls the function:
var params = new Array();
params["param1"] = param1;
params["param2"] = param2;
post_to_url('newTask.php', params, "get");
If I have the target attribute set to _blank so it opens a new tab, the function works just fine and I can see my params right there in the url bar.
But if I remove the target attribute (which I would prefer), it seems as if the page just refreshes. No params in the URL, and the page doesn't act as if it has received data.
Can someone help me track this down please?
Try using:
form.setAttribute("target", "_self");

Not able to send form parameters to the server

We are getting a issue wherein while submitting a form via javascript one of the parameters (invoiceCodes) is not sent to the server. Below is the snippet of the javascript code.
The flow is as follows. When user clicks on "Print" button validateTransition() method is called in which we make a ajax call. After response of that ajax we call couponPopup(url, invoiceCodes). In this function we submit newWinForm but sometimes invoiceCodes parameter is sent empty.
Also checkForInvoiceCode is true in this case which require user to input invoice codes
Is there anything wrong in the manner in which we are putting values in the form which may lead to invoiceCodes being not sent sometimes.
function couponPopup(url, invoiceCodes)
{
var selectedOrders = '';
$(".selectedOrder:checked").each(function() {
selectedOrders += $(this).val() + ',';
});
var frm = document.forms["newWinForm"];
frm.action = url;
frm.selectedShipments.value= selectedOrders;
frm.invoiceCodes.value = invoiceCodes;
console.log("Selected orders are "+selectedOrders);
console.log("Invoice codes with them in order are "+invoiceCodes);
document.getElementById("hiddenInvoiceCodes").value=invoiceCodes;
document.getElementById("hiddenselectedShipments").value=selectedOrders;
frm.submit();
return false;
}
function validateTransition() {
$('#statusChangeSuccess').hide();
$('#statusChangeFail').hide();
var selectedOrders = '';
var invoiceCodes = '';
var flag = 0;
var spaceError = 0;
var commaError = 0;
$(".selectedOrder:checked").each(function() {
selectedOrders += $(this).val() + ',';
<c:if test="${checkForInvoiceCode}">
var emptyPattern = /^\s*$/;
var commaPattern = /,/;
var inv_code = $("#invoice-code-" + $(this).val()).val().trim();
if (emptyPattern.test(inv_code)) {
spaceError = 1;
flag = 1;
}
if (commaPattern.test(inv_code)) {
commaError = 1;
flag = 1;
}
invoiceCodes += inv_code + ",";
</c:if>
});
if(selectedOrders=='') {
alert('Please select at least one order');
return false;
}
if ( flag ) {
if ( commaError ) {
alert('One or more specified codes have comma, please remove comma from them');
}
if ( spaceError ) {
alert('One or more specified codes has been left blank, please fill them up');
}
if ( !commaError && !spaceError ) {
alert('Please contact tech');
}
return false;
}
var inputdata = {"selectedShipments" : selectedOrders,
"statusCode" : "PRINT"
};
//this is where we are making an ajax call
jQuery(function($){
setTimeout(function(){
var ajaxUrl = '/product/update/';
$.ajax({url:ajaxUrl, type: "POST", dataType: 'json', data:inputdata , success: function(data) {
if(data['status'] == 'success') {
//couponPopup function is called where form is submitted
couponPopup("${path.http}/product/print/", invoiceCodes);
$('#statusChangeSuccess').html(data['message']).show();
$(".selectedOrder:checked").each(function() {
$("#row-" + $(this).val()).remove();
});
} else{
$('#statusChangeFail').html(data['message']).show();
}
}});
}, 10 );
});
return false;
}
<form id="newWinForm" name="newWinForm" action="" method="post" target="_blank" >
<input type="hidden" id="hiddenselectedShipments" name="selectedShipments" value="" />
<input type="hidden" id="hiddenInvoiceCodes" name="invoiceCodes" value="" />
</form>
Controller for the form. Invoice codes is sometimes empty even when we are sending it from client side.
#RequestMapping("/product/print")
public void printSelectedPendingOrders(#RequestParam("selectedShipments") String selectedShipments,
#RequestParam(defaultValue = "", value = "invoiceCodes", required = false) String invoiceCodes, ModelMap modelMap, HttpServletResponse httpResponse)
throws IOException, DocumentException, ParserConfigurationException, SAXException {

Categories