Add to cart button - Javascript/JQuery error - javascript

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

Related

Why I cannot open a CSV file using JQuery and FileContentResult

I'm trying to make an ajax call (I specifically don't want to do it using ActionLink).
I'm having a controller that is like this:
public IActionResult ExportUsers(List<string> listOfEmails)
{
/*some data processing*/
return File(result, "text/csv", "ExportCandidates.csv");
}
On the other side with ajax I do this simple call:
$.ajax({
url: '/Admin/Testcenter/GenerateInvitationPreview',
type: 'post',
data: {
//some input data to send to the controller ​
​},
​success: function (response) {
​)
​}
​});
I know there exists something for pdf files where you return a base64 file and with the response in the ajax call you just write something like pdfWindow.document.write(...) and this will open a new window with a pdf file.
Is there a way to extract the response for my CSV file and generate it so the user downloads it ?
USE NPOI Library for Excel Sheet Generation
//Generate Excel Sheet
try
{
Guid gid = Guid.NewGuid();
string ext = ".xls";
string[] Headers = { "Appointments Id", "Date of Appointment", "Doctor Name", "Patient Name", "Visit Type", "Status" };
string fileName = "AppointmentsExcelSheet_" + gid.ToString() + ext;
var serverpath = _env.ContentRootPath;
string rootpath = serverpath + "/wwwroot/ExcelSheets/" + fileName;
FileInfo file = new FileInfo(Path.Combine(rootpath, fileName));
var memorystream = new MemoryStream();
using (var fs = new FileStream(rootpath, FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Appointments List");
IRow row = excelSheet.CreateRow(0);
var font = workbook.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "Calibri";
font.Boldweight = (short)FontBoldWeight.Bold;
for (var i = 0; i < Headers.Length; i++)
{
var cell = row.CreateCell(i);
cell.SetCellValue(Headers[i]);
cell.CellStyle = workbook.CreateCellStyle();
cell.CellStyle.SetFont(font);
}
var result = _Appointment.GetAppoinmentsPDf();
int index = 1;
foreach (var app in result.Items)
{
//var PatientDob = Convert.ToDouble(app.PatientDOB);
row = excelSheet.CreateRow(index);
row.CreateCell(0).SetCellValue(app.AppointmentId);
row.CreateCell(1).SetCellValue(app.DateofAppointment+" "+app.TimeofAppointment);
row.CreateCell(2).SetCellValue(app.DoctorFullName);
row.CreateCell(3).SetCellValue(app.SelectedPatientName);
row.CreateCell(4).SetCellValue(app.PurposeofVisit);
if (app.IsActive == false)
{
row.CreateCell(5).SetCellValue("Inactive");
}
else
{
row.CreateCell(5).SetCellValue("Active");
}
index++;
}
workbook.Write(fs);
}
using (var filestream = new FileStream(rootpath, FileMode.Open))
{
filestream.CopyToAsync(memorystream);
}
memorystream.Position = 0;
//send filepath to JQuery function
response.Msg = "/ExcelSheets/" + fileName;
}
catch (Exception Ex)
{
//exception code
}
return Ok(reponse.Msg)
//JavaScript
function AppointmentsExcelSheet() {
//var token = Token;
//var link = path;
debugger
$.ajax({
//'Content-Type': 'application/pdf.',
type: "GET",
url: "/api/Appointments/GetAppointmentsExcelSheet",
beforeSend: function () {
$.blockUI({
message: ('<img src="/images/FadingLines.gif"/>'),
css: {
backgroundColor: 'none',
border: '0',
'z-index': 'auto'
}
});
},
complete: function () {
$.unblockUI();
},
success: function (data) {
debugger
//downloads your Excel sheet
window.location.href = data.msg;
}
});
}
The best way to do what you want to do is to not use AJAX, but use either a link click that opens a new window (since you are passing in parameters) If you could use a
<form target="_blank">
to open a form response. Inside the form can be a field or fields that contains the list of emails (it can be one field, or multiple input fields with the same name). Your action handler can accept that list, parse it, and return a File response, and the natural result of opening the new window from the form post operation is a file that opens up.

Changing url using javascript and jquery

Hello there
I am developing a jQuery plugin that loads files through ajax. When user clicks on a button which is:
<button class='btn btn-info' data-load="ajax" data-file="ajax/login.html" >Login</button>
When user clicks on button it generates following url:
http://localhost//plugins/ajaxLoad/index.html#ajax/Login
I want to change it to
http://localhost//plugins/ajaxLoad/index.html/ajax/Login
My javascript is:
(function ($) {
$.fn.ajaxLoad = function (options) {
var settings = $.extend({
fileUrl : 'null',
loadOn : '.em'
}, options);
$('[data-load="ajax"]').each(function(index, el) {
$(this).click(function () {
var file = $(this).attr('data-file');
var loadOn = $(this).attr('data-load-on');
var permission = $(this).attr("data-ask-permission");
settings.fileUrl = file;
settings.loadOn = loadOn;
if (permission == 'yes') {
var ask = confirm("Do you want to load file");
if (ask == true) {
$.fn.loadFile();
}
}else {
$.fn.loadFile();
}
});
});
$.fn.loadFile = function () {
// setting location;
var a = settings.fileUrl.split(".");
location.hash = a[0];
$.post(settings.fileUrl, function(response) {
$(settings.loadOn).html(response);
});
}
}
}(jQuery))
Can anyone tell me how to change url in jquery and Javascript.
You need to use history.pushstate() to do this.
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");
Have a look at this article on MDN for more details
https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method
This article gives some nice jQuery examples.
https://rosspenman.com/pushstate-jquery
Added another attribute title to button
<button data-title="login" class='btn btn-info' data-load="ajax" data-file="ajax/login.html" >Login</button>
In Js (after $(this).click line):
var title = $(this).attr('data-title');
settings.title = title
Just replace
location.hash = a[0];
With
history.pushState('','',"?"+settings.title);
Change
location.hash = a[0];
to:
location.pathname += '/' + a[0];
Just replace the hash with a blank using .replace()
Example .
settings.fileUrl.replace('.' , ' ');
Updated above also
UPDATE :
Don't hash the URL
Example :
$.fn.loadFile = function () {
// setting location;
var a = settings.fileUrl.replace("." , "/");
location.href = a;
$.post(settings.fileUrl, function(response) {
$(settings.loadOn).html(response);
});
}
}

right elFinder and CKeditor integration to upload files directly

I uses elFinder laravel package file Manager with ckeditor. I follow all Instructions step and all things work except one.
When I click on image button in ckEditor to select (or upload) an Image , on the upload tab after select an image from my computer and click Send it to the Server button NotFoundHttpException in RouteCollection.php line 161 shown and upload fails.
this is ckEditor initialization code :
<textarea name="content_fa" id="fa_post_content" class="form-control"
rows="10"></textarea>
<script>
var fa_post_content = CKEDITOR.replace('fa_post_content', {
toolbar: 'admin_mode',
filebrowserBrowseUrl : '{{route('elfinder.ckeditor')}}',
filebrowserUploadUrl : '/elfinder/connector.php?cmd=upload'
});
</script>
According to This Issue , I add filebrowserUploadUrl option as you see above. but this not work too.
How can I solve this ?
This code (+ DnD upload) using demo site is here.
CKEDITOR.on('dialogDefinition', function (event) {
var editor = event.editor,
dialogDefinition = event.data.definition,
tabCount = dialogDefinition.contents.length,
uploadButton, submitButton, inputId,
elfUrl = editor.config.filebrowserUploadUrl,
// elFinder configs
elfDirHashMap = { // Dialog name / elFinder holder hash Map
image : '',
flash : '',
files : '',
link : '',
fb : 'l1_Lw' // fallback target
},
customData = {}; // any custom data to post
for (var i = 0; i < tabCount; i++) {
uploadButton = dialogDefinition.contents[i].get('upload');
submitButton = dialogDefinition.contents[i].get('uploadButton');
if (uploadButton !== null && submitButton !== null) {
uploadButton.hidden = false;
submitButton.hidden = false;
uploadButton.onChange = function() {
inputId = this.domId;
}
submitButton.onClick = function(e) {
dialogName = CKEDITOR.dialog.getCurrent()._.name;
var target = elfDirHashMap[dialogName]? elfDirHashMap[dialogName] : elfDirHashMap['fb'],
name = $('#'+inputId),
input = name.find('iframe').contents().find('form').find('input:file'),
error = function(err) {
alert(err.replace('<br>', '\n'));
};
if (input.val()) {
var fd = new FormData();
fd.append('cmd', 'upload');
fd.append('overwrite', 0); // disable upload overwrite to make to increment file name
fd.append('target', target);
$.each(customData, function(key, val) {
fd.append(key, val);
});
fd.append('upload[]', input[0].files[0]);
$.ajax({
url: elfUrl,
type: 'POST',
data: fd,
processData: false,
contentType: false,
dataType: 'json'
})
.done(function( data ) {
if (data.added && data.added[0]) {
var url = data.added[0].url;
var dialog = CKEDITOR.dialog.getCurrent();
if (dialogName == 'image') {
var urlObj = 'txtUrl'
} else if (dialogName == 'flash') {
var urlObj = 'src'
} else if (dialogName == 'files' || dialogName == 'link') {
var urlObj = 'url'
} else {
return;
}
dialog.selectPage('info');
dialog.setValueOf(dialog._.currentTabId, urlObj, url);
} else {
error(data.error || data.warning || 'errUploadFile');
}
})
.fail(function() {
error('errUploadFile');
})
.always(function() {
input.val('');
});
}
return false;
}
}
}
});
For anyone running into this issue now, the thing that resolved it for me was setting filebrowserBrowseUrl. The mistake I was making was setting filebrowserUploadUrl instead of the filebrowserBrowseUrl. Elfinder handles the upload inside itself, so you should not have to use the 'send to the server' button at all, just the browse server button.
So the ckeditor code looked like such
CKEDITOR.replace('your-id-here', {
filebrowserBrowseUrl: '/elfinder/ckeditor',
}
);
noting to replace your-id-here with your own id.

TypeError: click called on object that does not implement interface HtmlElement

I've seen the other questions on this topics, but i can't spot the error in my code.
$('#submit_bulk').on('click',function(e){
var action = $('select[name="bulk_action"]'),
targets = $('table tr td:first-child :checkbox:checked');
if(action=='invalid' || targets.length == 0){
sk.alert('Nothing to do','warning');
return false;
}else{
$(this).html('Working....');
var fData = {
action: action,
mixtapes: '',
singles: ''
};
$.each(targets,function(i,v){
if($(this).data('type') == 'mixtape'){
fData.mixtapes += $(this).data('id')+',';
}else{
fData.singles += $(this).data('id')+',';
}
});
fData = $.param(fData);
console.log(fData); //i get no output here. is fData null?
$.post(window.location.origin+'/adminAPI/bulk_action',fData,function(data){
var data = JSON.parse(data);
if(data.error==0){
sk.alert('Your changes were saved','success');
//update view here.
}else{
sk.alert(data.message,'error');
}
});
$(this).html('go');
}
});
Word to the wise. make sure you are not passing a jQuery selector as a value into your form data.
the offending line was:
var action = $('select[name="bulk_action"]')
should have been:
var action = $('select[name="bulk_action"]').val()

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

Categories