I am novice in JS , and following is the code I found on Stackoverflow itself Can someone please explain on how this serialization takes place in the function below, stepwise process? Also once the serealization is done , how to parse through the JSON object to retrieve the info in tabular form ?
JAVASCRIPT
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
<!DOCTYPE HTML>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="demon.js"></script>
</head>
<body>
<h2>Form</h2>
<form action="" method="post">
First Name:<input type="text" name="Fname" maxlength="12" size="12"/> <br/>
Last Name:<input type="text" name="Lname" maxlength="36" size="12"/> <br/>
Gender:<br/>
Male:<input type="radio" name="gender" value="Male"/><br/>
Female:<input type="radio" name="gender" value="Female"/><br/>
Favorite Food:<br/>
Steak:<input type="checkbox" name="food[]" value="Steak"/><br/>
Pizza:<input type="checkbox" name="food[]" value="Pizza"/><br/>
Chicken:<input type="checkbox" name="food[]" value="Chicken"/><br/>
<textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
Select a Level of Education:<br/>
<select name="education">
<option value="Jr.High">Jr.High</option>
<option value="HighSchool">HighSchool</option>
<option value="College">College</option></select><br/>
Select your favorite time of day:<br/>
<select size="3" name="TofD">
<option value="Morning">Morning</option>
<option value="Day">Day</option>
<option value="Night">Night</option></select>
<p><input type="submit" /></p>
</form>
<h2>JSON</h2>
<pre id="result">
</pre>
</body>
</html>
This is what the code is doing
// create a jQuery plugin
$.fn.serializeObject = function() {
// return object to store the values
var o = {};
// call serializeArray on the form to get [{name: 'something', value: 'something'}]
var a = this.serializeArray();
// iterate over the serialized array
$.each(a, function() {
// if the value has already been defined on the object
if (o[this.name] !== undefined) {
// check if the value is not an array
if (!o[this.name].push) {
// it's not so instantiate a new array with the value in it
o[this.name] = [o[this.name]];
}
// add the value to the array of values
o[this.name].push(this.value || '');
} else {
// we are dealing with a new value so set it to the json object
o[this.name] = this.value || '';
}
});
// return the json serialized object from the plugin
return o;
};
Related
I copied this working code to use on my site but now that bootstrap is going to discontinue JQuery I want to change the below to vanilla javascript.
I'm a beginner and don't fully understand the logic behind it.
Can anyone help me write it in vanilla JS?
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
$(function() {
$('form').submit(function() {
$('#result').text(JSON.stringify($('form').serializeObject()));
return false;
});
});
I'm using the JS section of this code.
For a simple form that doesn't have array names you can use Object.fromEntries() and FormData API.
Note you will need a polyfill to use Object.fromEntries() in some lesser grade browsers
const form = document.querySelector('form')
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const res = Object.fromEntries(formData.entries());
const json = JSON.stringify(res, null, 4)
document.querySelector('textarea').value = json;
});
<form>
<button>Submit</button>
<select name="select">
<option value="1">1</option>
<option value="2" selected>2</option>
</select>
<input value="foo" name="text1">
<input value="" name="text2"> One: <input type="radio" name="radios" value="1"> Two: <input type="radio" name="radios" value="2" checked>
</form>
<hr/>
<strong>Results</strong>
<br/>
<textarea cols="40" rows="10"></textarea>
$('#submit-form').click(function(){
var data_serialize = $("#form").serialize();
$("input[type='checkbox']:not(:checked)").each(function(e){
data_serialize += "&"+this.name+'=0';
});
$("input[type='checkbox']:checked").each(function(e){
data_serialize += "&"+this.name+'=1';
});
console.log(data_serialize);
})
The above code gives me a string
companyName=&contactName=&role=&email=&phone=&desctiption=&websiteURL=&tc-check=0
like this. How can I make it as an Object?
It will convert this string to an javascript object.
var yourString = 'companyName=&contactName=&role=&email=&phone=&desctiption=&websiteURL=&tc-check=0';
var yourObj = JSON.parse('{"' + yourString.replace(/=/g,'":"').replace(/&/g, '","') + '"}');
console.log(JSON.stringify(yourObj));
You can easily loop through the form controls building an object via brackets notation:
$('#submit-form').click(function(){
var obj = {};
$("#form").find("input, textarea, select").each(function() {
var type = this.type.toLowerCase();
if (this.name && !this.disabled && type !== "button" && type !== "submit") {
if (type === "checkbox") {
obj[this.name] = this.checked ? 1 : 0;
} else {
obj[this.name] = $(this).val();
}
}
});
console.log(obj);
});
Note that we skip disabled inputs and inputs without names, as that's the standard for forms (it's what HTML does, and what serialize does). The above preserves your non-standard handling of checkboxes.
Example:
$('#submit-form').click(function(){
var obj = {};
$("#form").find("input, textarea, select").each(function() {
var type = this.type.toLowerCase();
if (this.name && !this.disabled && type !== "button" && type !== "submit") {
if (type === "checkbox") {
obj[this.name] = this.checked ? 1 : 0;
} else {
obj[this.name] = $(this).val();
}
}
});
console.log(obj);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form">
<input name="btn" type="button" value="Buttons are ignored">
<input name="text1" type="text" value="text here">
<input name="cb1" type="checkbox" checked>
<input name="cb2" type="checkbox">
<select name="s1">
<option value="foo" selected>foo</option>
<option value="bar">bar</option>
</select>
<textarea name="ta">testing</textarea>
<input name="text-disabled" type="text" disabled value="don't include me">
<input type="text" value="Ignore me I don't have a name">
<input type="button" id="submit-form" value="Submit">
</form>
I am having two forms in same page,
Form 1 ID : home /
Form 2 ID : contact
I need the values filled in the form(home) in the text box of form2(contact) once the send button clicked.
<form id="home" method="get" action="#portfolio" role="form">
<select class="form-control" id="pd_howmuch">
<option>HOW MUCH ?</option>
<option>$100</option>
<option>$200</option>
</select>
<input id="pd_fname" type="text" name="name">
<input id="pd_lname" type="text" name="surname">
<input id="pd_zipcode" type="tel" name="zipcode">
<input id="pd_applynowbt" type="submit" value="Send">
</form>
<section id="portfolio">
<form id="contact" method="post" action="contact.php" role="form">
<select class="form-control" id="howmuch1">
<option>HOW MUCH ?</option>
<option>$100</option>
<option>$200</option>
</select>
<input id="fname1" type="text" name="name">
<input id="lname2" type="text" name="surname">
<input id="zipcode2" type="tel" name="zipcode">
<input id="applynowbt" type="submit" value="Submit">
</form>
</section>
Ok If I am understanding you correctly you wish to populate information from the first form to the second one.
So for this task to be accomplish you need to attach an event handler to the second form and prevent the default behavior
Working demo Hope to help you
var homeForm = document.getElementById("home");
var contactForm = document.getElementById("contact");
contactForm.addEventListener("submit", function(e) {
e.preventDefault();
contactForm.elements.item(0).value = homeForm.elements.item(0).value
contactForm.elements.item(1).value = homeForm.elements.item(1).value
contactForm.elements.item(2).value = homeForm.elements.item(2).value
contactForm.elements.item(3).value = homeForm.elements.item(3).value
}, false);
var sourceForm = document.getElementById("source-form");
var targetForm = document.getElementById("target-form");
function findTargetNode(nodeName, name) {
var targetElems = targetForm.elements;
for (var i = 0; i < targetElems.length; i++) {
var elem = targetElems.item(i);
if (elem.nodeName.toLowerCase() === nodeName && elem.name === name) {
return elem;
}
}
}
function setNodeValue(node, type, value) {
if (type === 'select')
{
for (var i = 0, options = node.options; i < options.length; i++) {
if (options[i].value === value) {
options[i].setAttribute('selected', 'true');
}
else {
options[i].removeAttribute('selected');
}
}
}
// else if (type === 'checkbox' || type === 'radio') { /* ... */ }
else {
node.value = value;
}
}
sourceForm.addEventListener("submit", function(e) {
for (var i = 0, elems = sourceForm.elements; i < elems.length; i++) {
var elem = elems.item(i);
if (!elem.name) {
continue;
}
var type = elem.nodeName.toLowerCase();
var targetNode = findTargetNode(type, elem.name);
if (!targetNode) {
continue;
}
setNodeValue(targetNode, type, elem.value);
}
e.preventDefault();
// targetForm.submit();
}, false);
<form id="source-form" action="javascript:void(0)" role="form">
<select class="form-control" id="my-select" name="my-select">
<option value="-1">HOW MUCH ?</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input id="my-text" type="text" name="my-text">
<input id="submit-source-form" type="submit" value="Fill the following form">
</form>
<section style="margin-top: 15px;">
<form id="target-form" method="post" action="contact.php" role="form">
<select class="form-control" id="my-select-2" name="my-select">
<option value="-1">HOW MUCH ?</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input id="my-text-2" type="text" name="my-text" value="this will change">
<input id="additional-value" type="text" name="additional" placeholder="this value will not change">
<input id="submit-target-form" type="submit" value="Send form">
</form>
</section>
https://jsfiddle.net/cremugnt/
Note: "Send form" action doesn't work here because of "Blocked form submission to 'http://stacksnippets.net/contact.php' because the form's frame is sandboxed and the 'allow-forms' permission is not set."
Note: This snippet can copy only "select" and "input" fields so if you want to work with other fields like "checkbox" or "radio" you get the idea.
This is a more global approach using OODK-JS and jQuery compatible with any types of field (note as field matching is based on the name attribute ):
$.noConflict();
OODK.config({
'path': {
'oodk': '../src',
'workspace': 'workspace'
}
});
OODK(function($, _){
// POO approach to solve this problem
// define a FormHelper class
var FormHelper = $.class(function($, µ, _){
$.protected('form');
$.public(function __initialize(form){
µ.form = form;
});
$.public(function exportToLiteral(){
var exprt = {};
jQuery(µ.form).find(":input, [textarea]").each(function(){
var val;
if(this.type === 'radio'){
val = µ.exportRadioField(this, exprt);
}else if(this.type === 'checkbox'){
val = µ.exportCheckboxField(this, exprt);
}else{
val = µ.exportField(this, exprt);
}
if(typeof val !== "undefined" &&
typeof jQuery(this).attr("name") !== "undefined"){
exprt[jQuery(this).attr("name")] = val;
}
});
return exprt;
});
// export argument html field fld to object literal exprt
$.protected(function exportField(fld, exprt){
return jQuery(fld).val();
});
// export argument checkbox html field fld to object literal exprt
$.protected(function exportCheckboxField(fld, exprt){
var val;
if(jQuery(fld).is(':checked')){
if(typeof exprt[jQuery(this).attr("name")] !== "undefined"){
val = exprt[jQuery(this).attr("name")];
}else{
val = [];
}
val.push(jQuery(this).val());
};
return val;
});
// export argument html radio field fld to object literal exprt
$.protected(function exportRadioField(fld, exprt){
var val;
if(jQuery(fld).is(':checked')){
val = jQuery(this).val();
}
return val;
});
// copy all values of the source form to the destination form passed
// as argument
$.public(function copyToForm(destForm){
var oSrcForm = this.exportToLiteral();
jQuery(destForm).find(":input, [textarea]").each(function(){
if(typeof oSrcForm[jQuery(this).attr("name")] !== "undefined"){
var srcVal = oSrcForm[jQuery(this).attr("name")];
if(this.type == 'checkbox'){
µ.copyToCheckboxField(this, srcVal, oSrcForm);
}else if(this.type == 'radio'){
µ.copyToRadioField(this, srcVal, oSrcForm);
}else{
µ.copyToField(this, srcVal, oSrcForm);
}
}
});
});
$.protected(function copyToField(fld, val, exprt){
jQuery(fld).val(val);
});
$.protected(function copyToCheckboxField(fld, val, exprt){
if(Array.isArray(srcVal) && srcVal.indexOf(jQuery(fld).val()) !== -1){
jQuery(fld).prop('checked', true);
}
});
$.protected(function copyToRadioField(fld, val, exprt){
if(exprt[jQuery(fld).attr("name")] == jQuery(fld).val()){
jQuery(fld).prop('checked', true);
}
});
});
jQuery(document).ready(function(){
jQuery('#pd_applynowbt').bind('click', function(evt){
// prevent the source form to be submitted
evt.preventDefault();
var formHelper = $.new(FormHelper, jQuery('#home'));
// copy all fields from form #home to form #contact
formHelper.copyToForm(jQuery('#contact'));
});
});
});
How do i modify this code to get the intended outcome.
This is what i get from this code.
{"name":"abc","identifier":"abc_one","number":"55","description":"This is a description"}
But i want a json object like this,
{"project":
{"name":"abc",
"identifier":"abc_one",
"number":"55",
"description":"This is a description"}
}
Please look at the code i have at the moment. It Need to be warped by a another object call "project".
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
$(function() {
$('form').submit(function() {
$('#result').text(JSON.stringify($('form').serializeObject()));
return false;
});
});
<form action="" method="post">
First Name:<input type="text" name="name" maxlength="12" size="12"/> <br/>
Last Name:<input type="text" name="identifier" maxlength="36" size="12"/> <br/>
number:<input type="number" name="number" maxlength="36" size="12"/> <br/>
<textarea wrap="physical" cols="20" name="description" rows="5">Enter your favorite quote!</textarea><br/>
Select a Level of Education:<br/>
<p><input type="submit" /></p>
</form>
All you need to change is following
return o;
To
return {"project":o}
in serializeObject function.
Edited:
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
var value = this.value || '';
if (/^\d+$/.test(value))
value = +value;
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(value);
} else {
o[this.name] = value;
}
});
return o;
};`
Edited to hopefully make clearer.
Having difficulty wrapping my head around this - sleep deprivation = madness.
I have a form that simply serialises the data into JSON and stores it for later use.
<form id="form" method="post">
a? <input class="number" type="text" name="a" size="5" maxlength="5"/><br/>
Item 1:
Type?:<br/>
<select size="2" name="type">
<option value="1">b</option>
<option value="2">c</option>
</select>
d:<input class="number" type="text" name="d" maxlength="2" size="2"/> <br/>
e:<input class="number" type="text" name="e" maxlength="2" size="2"/> <br/>
<p>Item 2:</p>
Type?:<br/>
<select size="2" name="type">
<option value="1">b</option>
<option value="2">c</option>
</select>
d:<input class="number" type="text" name="d" maxlength="2" size="2"/> <br/>
e:<input class="number" type="text" name="e" maxlength="2" size="2"/> <br/>
<input type="submit" />
when the form is serialised the result I get is:
JSON{
"a":1,
"type":[1,2],
"d":[99,33],
"e":[99,33]
}
what I need is the typical tree structure of JSON something where each item has its own level, something like:
{
"a": "1",
"item1":
{
"type": "1",
"d": "99",
"e": "99",
},
"item2":
{
"type": "2",
"d": "33",
"e": "33",
}
Ideally I'd like to have an option whereby the user can state how many items the form should request information for but I need a basic working example first.
once I have this data I'm then converting it into JSON and would like a tree like structure if possible. Any help appreciated. This post How to serialize a form into an object (with tree structure)? helps a lot but its the structure of the HTML I'm having issues with. Thanks again.
A quick and dirty way would be this: change the name of your inputs based on their item number:
<input name="item1.a" ... />
<input name="item2.a" ... />
<input name="item3.a" ... />
Then modify the serializeObject() to look for the dots:
...
$.each(a, function() {
var value = this.value || '';
if (/^\d+$/.test(value))
value = +value;
if ( this.name && this.name.indexOf('.') )
{
var split = this.name.split('.');
o[ split[0] ] = o[ split[0] ] || {};
o[ split[0] ][ split[1] ] = value
}
else if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(value);
} else {
o[this.name] = value;
}
});
...
NOTE: This code isn't perfect, but it will get you in the right direction!
I'd introduce new html attribute:
<input data-item="1" class="number" type="text" name="d" maxlength="2" size="2"/>
<select data-item="1" size="2" name="type"> ...
and then I'd use
$(this).attr('data-item');
to read value and place it in right object. Other option is to get elements only for specified item (in some loop):
$('input[data-item="1"], select[data-item="1"]').each(...);
EDIT
I see no pretty way of using serializeArray() to achieve this, but I'd go for item number in name attribute (name="type1") or again for loop with i as item number:
$('[data-item="'+i+'"]', this).serializeArray();