I'm working with a form for which the mark-up I can't change & can't use jQuery.
Currently the form post the results to a new window. Is it possible to change this to an ajax form so that the results displays on submit instead without altering any mark-up?
Pulling the results (mark-up) from the results page back to the form page.
Here is the mark-up for the form.
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite" target="_blank">
<div class="form-item">
<fieldset class="form-radio-group">
<legend><span class="legend-text">What mobile phone is the best?</span></legend>
<div class="form-radio-item">
<input type="radio" class="radio" value="1225962377541" name="option" id="form-item-1225962377541">
<label class="radio" for="form-item-1225962377541">
<span class="label-text">iPhone</span>
</label>
</div><!-- // .form-radio-item -->
<div class="form-radio-item">
<input type="radio" class="radio" value="1225962377542" name="option" id="form-item-1225962377542">
<label class="radio" for="form-item-1225962377542">
<span class="label-text">Android</span>
</label>
</div><!-- // .form-radio-item -->
<div class="form-radio-item">
<input type="radio" class="radio" value="1225962377543" name="option" id="form-item-1225962377543">
<label class="radio" for="form-item-1225962377543">
<span class="label-text">Symbian</span>
</label>
</div><!-- // .form-radio-item -->
<div class="form-radio-item">
<input type="radio" class="radio" value="1225962377544" name="option" id="form-item-1225962377544">
<label class="radio" for="form-item-1225962377544">
<span class="label-text">Other</span>
</label>
</div><!-- // .form-radio-item -->
</fieldset>
</div><!-- // .form-item -->
<div class="form-item form-item-submit">
<button class="button-submit" type="submit"><span>Vote now</span></button>
</div><!-- // .form-item -->
<input type="hidden" name="c" value="News_Poll">
<input type="hidden" class="pollId" name="cid" value="1225962377536">
<input type="hidden" name="pagename" value="Foundation/News_Poll/saveResult">
<input type="hidden" name="site" value="themouth">
Any tips/tutorial is much appreciated. :)
The following is a far more elegant solution of the other answer, more fit for modern browsers.
My reasoning is that if you need support for older browser you already most likely use a library like jQuery, and thus making this question pointless.
/**
* Takes a form node and sends it over AJAX.
* #param {HTMLFormElement} form - Form node to send
* #param {function} callback - Function to handle onload.
* this variable will be bound correctly.
*/
function ajaxPost (form, callback) {
var url = form.action,
xhr = new XMLHttpRequest();
//This is a bit tricky, [].fn.call(form.elements, ...) allows us to call .fn
//on the form's elements, even though it's not an array. Effectively
//Filtering all of the fields on the form
var params = [].filter.call(form.elements, function(el) {
//Allow only elements that don't have the 'checked' property
//Or those who have it, and it's checked for them.
return typeof(el.checked) === 'undefined' || el.checked;
//Practically, filter out checkboxes/radios which aren't checekd.
})
.filter(function(el) { return !!el.name; }) //Nameless elements die.
.filter(function(el) { return el.disabled; }) //Disabled elements die.
.map(function(el) {
//Map each field into a name=value string, make sure to properly escape!
return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
}).join('&'); //Then join all the strings by &
xhr.open("POST", url);
// Changed from application/x-form-urlencoded to application/x-form-urlencoded
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//.bind ensures that this inside of the function is the XHR object.
xhr.onload = callback.bind(xhr);
//All preperations are clear, send the request!
xhr.send(params);
}
The above is supported in all major browsers, and IE9 and above.
Here's a nifty function I use to do exactly what you're trying to do:
HTML:
<form action="/cs/Satellite">...</form>
<input type="button" value="Vote now" onclick="javascript:AJAXPost(this)">
JS:
function AJAXPost(myself) {
var elem = myself.form.elements;
var url = myself.form.action;
var params = "";
var value;
for (var i = 0; i < elem.length; i++) {
if (elem[i].tagName == "SELECT") {
value = elem[i].options[elem[i].selectedIndex].value;
} else {
value = elem[i].value;
}
params += elem[i].name + "=" + encodeURIComponent(value) + "&";
}
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("POST",url,false);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", params.length);
xmlhttp.setRequestHeader("Connection", "close");
xmlhttp.send(params);
return xmlhttp.responseText;
}
Nowadays using FormData is the easiest method. You construct it with a reference to the Form element, and it serializes everything for you.
MDN has an example of this here -- roughly:
const form = document.querySelector("#debarcode-form");
form.addEventListener("submit", e => {
e.preventDefault();
const fd = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.addEventListener("load", e => {
console.log(e.target.responseText);
});
xhr.addEventListener("error", e => {
console.log(e);
});
xhr.open("POST", form.action);
xhr.send(fd);
});
and if you want it as an object (JSON):
const obj = {};
[...fd.entries()].forEach(entry => obj[entry[0]] = entry[1]);
Expanding on Madara's answer: I had to make some changes to make it work on Chrome 47.0.2526.80 (not tested on anything else). Hopefully this can save someone some time.
This snippet is a modification of that answer with the following changes:
filter !el.disabled,
check type of input before excluding !checked
Request type to x-www-form-urlencoded
With the following result:
function ajaxSubmit(form, callback) {
var xhr = new XMLHttpRequest();
var params = [].filter.call(form.elements, function (el) {return !(el.type in ['checkbox', 'radio']) || el.checked;})
.filter(function(el) { return !!el.name; }) //Nameless elements die.
.filter(function(el) { return !el.disabled; }) //Disabled elements die.
.map(function(el) {
return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
}).join('&'); //Then join all the strings by &
xhr.open("POST", form.action);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onload = callback.bind(xhr);
xhr.send(params);
};
The strategy is to serialise the form and send the data using XHR, then do what you want with the response. There is a good set of utilities and help at Matt Krus's Ajax Toolbox and related Javascript Toolbox.
If you are just serialising the form posted, then the following will do the trick. It can easily be extended to include other form control types:
var serialiseForm = (function() {
// Checkboxes that have already been dealt with
var cbNames;
// Return the value of a checkbox group if any are checked
// Otherwise return empty string
function getCheckboxValue(cb) {
var buttons = cb.form[cb.name];
if (buttons.length) {
for (var i=0, iLen=buttons.length; i<iLen; i++) {
if (buttons[i].checked) {
return buttons[i].value;
}
}
} else {
if (buttons.checked) {
return buttons.value;
}
}
return '';
}
return function (form) {
var element, elements = form.elements;
var result = [];
var type;
var value = '';
cbNames = {};
for (var i=0, iLen=elements.length; i<iLen; i++) {
element = elements[i];
type = element.type;
// Only named, enabled controls are successful
// Only get radio buttons once
if (element.name && !element.disabled && !(element.name in cbNames)) {
if (type == 'text' || type == 'hidden') {
value = element.value;
} else if (type == 'radio') {
cbNames[element.name] = element.name;
value = getCheckboxValue(element);
}
}
if (value) {
result.push(element.name + '=' + encodeURIComponent(value));
}
value = '';
}
return '?' + result.join('&');
}
}());
A modern way using fetch would be:
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData
});
Note browser support and use this polyfil if IE-support is needed
function ajaxSubmit(form, callback) {
var xhr = new XMLHttpRequest();
var params = [].filter.call(form.elements, function (el) {return !(el.type in ['checkbox', 'radio']) || el.checked;})
.filter(function(el) { return !!el.name; }) //Nameless elements die.
.filter(function(el) { return !el.disabled; }) //Disabled elements die.
.map(function(el) {
if (el.type=='checkbox') return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.checked);
else return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
}).join('&'); //Then join all the strings by &
xhr.open("POST", form.action);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onload = callback.bind(xhr);
xhr.send(params);
};
I just took Coomie's answer above and made it work for Radio/Checkboxes. I can't believe how simple and clear this is. With a few exceptions, I'm done using frameworks.
var params = "";
var form_elements = form.elements;
for (var i = 0; i < form_elements.length; i++)
{
switch(form_elements[i].type)
{
case "select-one":
{
value = form_elements[i].options[form_elements[i].selectedIndex].value;
}break;
case "checkbox":
case "radio":
{
if (!form_elements[i].checked)
{
continue; // we don't want unchecked data
}
value = form_elements[i].value;
}break;
case "text" :
{
value = form_elements[i].value;
}break;
}
params += encodeURIComponent(form_elements[i].name) + "=" + encodeURIComponent(value) + "&";
}
var xhr = new XMLHttpRequest();
xhr.open('POST', "/api/some_url");
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200)
{
console.log("xhr.responseText");
}
else
{
console.log("Error! Status: ", xhr.status, "Text:", xhr.responseText);
}
}
};
console.log(params);
xhr.send(params);
Here's the simplest method I came up with. I haven't found an example that uses this exact approach. The code submits the form using a non-submit type button and places the results into a div, if the form is not valid (not all required fields filled), it will ignore the submit action and the browser itself will show which fields are not filled correctly.
This code only works on modern browsers supporting the "FormData" object.
<script>
function ajaxSubmitForm() {
const form = document.getElementById( "MyForm" );
if (form.reportValidity()) {
const FD = new FormData( form );
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("content_area").innerHTML = this.responseText; } };
xhttp.open("POST","https://example.com/whatever.php",true);
xhttp.send( FD );
}
}
</script>
<div id="content_area">
<form id="MyForm">
<input type="hidden" name="Token" Value="abcdefg">
<input type="text" name="UserName" Value="John Smith" required>
<input type="file" accept="image/jpeg" id="image_uploads" name="ImageUpload" required>
<button type="button" onclick="ajaxSubmitForm()">
</form>
</div>
Related
I am very new to JS and I have a problem to create a searchable movie reviewer html page, it is very basic, I just want to know how to have the input box search the NYT API for the movie I am looking for, I wont have a problem putting the elements onto the page, I just want to know how to search properly. I expect I need a function that when the search button is clicked it requests from the site all movies with the words provided.
<div id="search">
<input type="text" id = "search">
<button onclick="search()">Search</button>
</div>
<textarea id="APIoutput" cols="90" rows="50"></textarea>
const ISFINISHED = 4;
const ISOK = 200;
var searchedMovie = document.getElementById("search").value;
function getJSONSync(url){
var response = "";
var xmlHttp = new XMLHttpRequest();
if(xmlHttp !== null){
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
response = xmlHttp.responseText;
}
return response;
}
function getJSONAsync(url, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === ISFINISHED && request.status === ISOK) {
callback(this);
}
};
request.open("GET", url);
request.send();
}
function search(searchedMovie){
var my_api_url = "https://api.nytimes.com/svc/movies/v2/reviews/search.json?query=" + searchedMovie + "&api-key=" + API;
return my_api_url;
}
function handleAPIresponse(response) {
var textArea = document.getElementById("APIoutput");
textArea.value = response.responseText;
}
getJSONAsync(my_api_url, handleAPIresponse);
ERRORS: Uncaught ReferenceError: my_api_url is not defined
Expected Results: (UNFORMATTED JSON THAT LOOKS LIKE THIS:)
{"status":"OK","copyright":"Copyright (c) 2021 The New York Times
Company. All Rights
Reserved.","has_more":false,"num_results":10,"results":[{"display_title":"The
Black Godfather","mpaa_rating":"TV-MA","critics_pick":0,"byline":"BEN
KENIGSBERG","headline":"‘The Black Godfather’ Review: The Music
Executive Who Made It All Happen"
On submit, I want to send form data to json. I want to use json so I can send the data to Python for processing. I am not using jquery.
I have the following HTML code:
<form id="frm1">
<label for="first">First name: <input type="text" id="first" name="first"></label><br><br>
<label for="last">Last name: <input type="text" id="last" name="last"></label><br>
<input type="submit" value="Submit">
</form>
I attempted to send the data to JSON using the following JS code:
form.addEventListener('submit', sendData)
function sendData(event){
//retreives form input
const first = form.querySelector('input[name="first"]');
const last = form.querySelector('input[name="last"]');
var xhr = new XMLHttpRequest();
var url = "formResults.json";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.first+ ", " + json.last);
}
};
var data = JSON.stringify({first, last});
xhr.send(data);
}
I am running the code in a local server and am seeing no output to the json file or any error code.
How do I get my form data to json?
Novice coder
This really is quite an open question. You have provided no details on the model in which the data needs to be provided as. I'm going to assume you need an object similar to the below.
{
first: 'John',
last: 'Smith'
}
If this is the case, you could use the below code.
var serializeForm = function (form) {
// Setup our serialized data
var serialized = {};
// Loop through each field in the form
for (var i = 0; i < form.elements.length; i++) {
var field = form.elements[i];
// Don't serialize fields without a name, submits, buttons, file and reset inputs, and disabled fields
if (!field.name || field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') continue;
// If a multi-select, get all selections
if (field.type === 'select-multiple') {
for (var n = 0; n < field.options.length; n++) {
if (!field.options[n].selected) continue;
serialized[field.name] = field.options[n].value
}
}
// Convert field data to a query string
else if ((field.type !== 'checkbox' && field.type !== 'radio') || field.checked) {
serialized[field.name] = field.value
}
}
return serialized;
};
Then you could use your code ...
form.addEventListener('submit', sendData)
function sendData(event){
//retreives form input
const formData = serializeForm(form);
var xhr = new XMLHttpRequest();
var url = "YOUR_ENDPOINT_NEEDS_TO_GO_HERE";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json);
}
};
var data = JSON.stringify(formData);
xhr.send(data);
}
You can see the above using the codepen linked here. In the example, the object is created immediately, so right-click anywhere in the preview window, view console and you'll see the output of the serializeForm method.
Credit goes to: https://gomakethings.com/how-to-serialize-form-data-with-vanilla-js/ where I got the initial code from and modified it to your (assumed) needs.
How do you insert the correct "xhr" value into the HTML5 button?
I am not sure how this whole XMLHttpRequest works. I believe it takes: xml data, text, numbers or null from the HTML5 button input and prints it out in text input in this case but can it store a value in it to call on it later. That is the question!
<script type="text/javascript">
function readBody(xhr) {
var data;
if (!xhr.responseType || xhr.responseType === "text"){
data = xhr.responseText;
} else if (xhr.responseType === "document") {
data = xhr.responseXML;
} else {
data = xhr.response;
}
window.document.myform.xhr1.value = data;
return data;
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200); {
window.document.myform.readBodyxhr.value = readBody(xhr);
}
else {
alert(xhr.status);
}
xhr.open('GET', 'http://www.google.com', true);
xhr.send(null);
}
</script>
...HTML5
<input type="button" name="XMLHttpRequest" value="XMLHttpRequest" onclick="readBody(xhr)" />
<input type="text" name="xhr1" value="" size="4"/></td>
<input type="text" name="readBodyxhr" value="" size="4"/></td>
Move call to .open() and .send() outside of onreadystatechange handler.
Substituted onload and onerror for onreadystatechange. ; following if condition is a syntax error. Note also, XMLHttpRequest with true passed at third parameter at .open() sets load handler to return results asynchronously.
<script type="text/javascript">
var url = "https://gist.githubusercontent.com/guest271314/6a76aa9d2921350c9d53/raw/1864137bfd2eb62705bd0e71175048a28b3253e6/abc.txt";
function readBody() {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
window.document.myform
.readBodyxhr.value = xhr.responseText;
}
xhr.onerror = function() {
alert(xhr.status);
}
xhr.open("GET", url, true);
xhr.send(null);
}
</script>
...HTML5
<form name="myform">
<input type="button" name="XMLHttpRequest" value="XMLHttpRequest" onclick="readBody()" />
<input type="text" name="xhr1" value="" size="4" />
<input type="text" name="readBodyxhr" value="" size="4" />
</form>
In the below JavaScript, I am unable to send radio button data to PHP. Example: if radio button "Mother" is selected, the selected value of "Mother" should be send through ajax. But my problem is that I am unable to send the selected radio button value from ajax. I Google'd it, but I am unable to solve it. Can you share the code for solving this problem.
This is the JavaScript code:
<script language="JavaScript">
var HttPRequest = false;
function doCallAjax() {
var test = $("#txtUsername").val();
var test2 = $("#txtPassword").val();
if(test=='')
{
alert("Please Enter Register Number");
}
else if(test2=='')
{
alert("Please Enter Date Of Birth");
}
else
{
HttPRequest = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
HttPRequest = new XMLHttpRequest();
if (HttPRequest.overrideMimeType) {
HttPRequest.overrideMimeType('text/html');
}
} else if (window.ActiveXObject) { // IE
try {
HttPRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
HttPRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!HttPRequest) {
alert('Cannot create XMLHTTP instance');
return false;
}
**// iam using this For Validation to send data to different urls based on selection**
var game1 = $('input[type="radio"]:checked').val();
if (game1 === "Mother") {
var url = 'http://localhost:9999/check.php';
}
else if (game1 === "Father") {
alert('Father');
}
else {
HttPRequest = false;
alert('select 1');
}
**this is Where ima stucked**
var pmeters = "tUsername=" + encodeURI( document.getElementById("txtUsername").value) +
"&tPassword=" + encodeURI( document.getElementById("txtPassword").value );
"&game=" + $('input[type="radio"]:checked').val();
HttPRequest.open('POST',url,true);
HttPRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
HttPRequest.setRequestHeader("Content-length", pmeters.length);
HttPRequest.setRequestHeader("Connection", "close");
HttPRequest.send(pmeters);
HttPRequest.onreadystatechange = function()
{
if(HttPRequest.readyState == 3) // Loading Request
{
document.getElementById("mySpan").innerHTML = "Now is Loading...";
}
if(HttPRequest.readyState == 4) // Return Request
{
if(HttPRequest.responseText == 'Y')
{
window.location = 'success.html';
}
else if (HttPRequest.responseText == 'z')
{
document.getElementById("mySpan").innerHTML = "";
window.alert("bad registernumber or dob");
}
else if (HttPRequest.responseText == 'b')
{
document.getElementById("mySpan").innerHTML = "";
window.alert("userexist");
}
}
}
}
}
</script>
This is html code
<br/>
<input type="radio" name="game" value="Mother">Mother
<br />
<input type="radio" name="game" value="Father">Father
<br />
<input type="radio" name="game" value="Self">Self
<br />
<input type="radio" name="game" value="Other">Other
<br />
</table>
<br>
<input name="btnLogin" type="button" id="btnLogin" OnClick="JavaScript:doCallAjax();" value="Login">
First I would suggest you to use jQuery, because it is really simplier and better.
Then you can use the following code to post the checkbox/radio value:
$("#game").val()
Here you can find the really simple syntax for Ajax with jQuery.
Please remove $('input[type="radio"]:checked').val() and replace with a var game. Before that please use below code to get value of checked radio button in var game.
var elements = document.getElementsByName("game");
var game;
for(var i = 0; i < elements.length; i++ ){
if(elements[i].checked){
game = elements[i].value;
}
}
So now your code will look like
var pmeters = "tUsername=" + encodeURI( document.getElementById("txtUsername").value) +
"&tPassword=" + encodeURI( document.getElementById("txtPassword").value );
"&game=" + game;
I have problem with the code further down.
In html file:
<form id='changeAccountForm' action='usermenu.php' method='post'>
Name:<input type="text" name="name"/>
Surname:<input type="text" name="surname"/>
Password:<input type="password" name="password"/>
Phone:<input type="text" name="phone"/>
Paid mail:<input type="text" name="paidMail"/>
Payment method:<input type="radio" name="paymentMethod" value="0"/>paypal
<input type="radio" name="paymentMethod" value="1"/>payza
<div id="changeAccountInformation" >change</div>
</form>
In Javascript file I use Javascript and jQuery. I use javascript with ajax and the function called:
function ajaxInit(){
var ajaxRequest;
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
}catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
}catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
}catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
return ajaxRequest;
}//end function ajaxInit
function updateUserDataWithAjax(){
var ajaxRequest = ajaxInit();
// Create a function that will receive data
// sent from the server and will update
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
// find all form elements and add the responseText to placeholder attribute
var childNodes = $("#changeAccountForm").children(),i,j=0;
var inputAjaxRequest = ajaxRequest.responseText;
//inputAjaxRequest = inputAjaxRequest.plit(",");//ERROR:
for(i=0; i<childNodes.length; i++)
if(childNodes[i]!= "input"){
childNodes[i].setAttribute("placeholder",inputAjaxRequest[j++]);
}
}
}
var namesArray = "userId,password,name,phone,";
namesArray+= "surname,paidMail,payMethod,";
namesArray+= "score";
namesArray = namesArray.split(',');
//gets all the childnodes and find these with attribute
var childNodes = $("#changeAccountForm").children(),values,names,i;
var queryString = '';
var first = true;
for(i=0; i<childNodes.length; i++)
for(j=0;j<namesArray.length;j++)
if(childNodes[i].getAttribute("name")==namesArray[j]){
values = childNodes[i].value;
names = childNodes[i].getAttribute("name");
if (first){
queryString += names+"="+values;
first = false;
}else
queryString += "&"+names+"="+values;
}
ajaxRequest.open("POST", "usermenu.php", true);
ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajaxRequest.setRequestHeader("Content-length", queryString .length);
ajaxRequest.setRequestHeader("Connection", "close");
ajaxRequest.send(queryString);
}
//and i call this function
$(document).ready( function(){
$("#changeAccountInformation").click(function(){
var user = updateUserDataWithAjax();
});
});
In php file:
when i use the method post something going wrong and prints Undefined index: [key value name] in. The response text from ajax is an array with the name of html file.
include "userMenu.html";
isset($_POST['name']);
echo $_POST['name'];
Any information will be appreciated, thank you.