jQuery - reproduce serialize() - javascript

I have multiple div elements and each one has a set of form fields (text inputs and selects).
Instead of the name attribute these fields have a rel attribute that has the same value as "name" should have.
How can I reproduce the behaviour of jQuery's serialize (http://api.jquery.com/serialize/) on these fields?
the HTML looks like this:
<div>
<input type="text" rel="title" value="bla" />
<input type="text" rel="count" value="5" />
<select rel="page">
<option value="home">home</option>
<option value="about" selected="selected">about</option>
<option value="404">404</option>
</select>
<input type="hidden" name="serialize_above_fields[]" value="" />
</div>
<div>
<input type="text" rel="title" value="bla" />
<input type="text" rel="count" value="5" />
<select rel="page">
<option value="home">home</option>
<option value="about" selected="selected">about</option>
<option value="404">404</option>
</select>
<input type="hidden" name="serialize_above_fields[]" value="" />
</div>
...
basically I want to produce a hidden input field with all the values of fields within the div it resides (and use rel's as keys), like:
<input type="hidden" name="serialize_above_fields[]" value="title=bla&count=5&page=check2&page=about" />

You can use jQuery's map utility to do that pretty easily.
$('div').each(function() {
var serializedData = $(this).find(':text, select').map(function(i, el) {
return $(el).attr('rel') + '=' + $(el).val();
}).get();
$(this).find('input[type=hidden]').val(serializedData.join('&'));
});

If your input elements are all within a <form></form>, You could try to serialize your form using something like this:
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.rel]) {
if (!o[this.rel].push) {
o[this.rel] = [o[this.rel]];
}
o[this.rel].push(this.value || '');
} else {
o[this.rel] = this.value || '';
}
});
return o;
};

Related

ComboBox to select only data in the list but submit their 3 digit code HTML5

I want to add a input box in my form where users can select airport similar to the one in this website (http://www.wego.pk/) Like when you type on the Destination Input, you get a list of possible values with detailed suggestion including city name + country name but when user submits the form the value submitted is the 3 digit code for the airport.
I tried html5 combobox as:
<form>
<input type="text" name="product" list="productName"/>
<datalist id="productName">
<option value="ISB">Pen</option>
<option value="KHI">Pencil</option>
<option value="PWH">Paper</option>
</datalist>
<input type="submit">
</form>
But if I type Pen then no suggestion comes. Kindly share some code snippet or any library for this purpose.
I will recommend to use an autocomplete plugin (e.g. jQuery UI autocomplete) instead HTML5 datalist. However, if the question is regarding the datalist, you can populate the product code into hidden field:
<form>
<input type="hidden" name="productCode" id="productCode" value="">
<input type="text" name="product" id="product" list="productName" autocomplete="off">
<datalist id="productName">
<option data-code="ISB">Pen</option>
<option data-code="KHI">Pencil</option>
<option data-code="PWH">Paper</option>
</datalist>
<input type="submit">
</form>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script>
$(function() {
// use "bind" instead "on" with jQuery lt 1.7
$("#product").on("input", function(e) {
var val = $(this).val();
var listId = $(this).attr("list");
var $option = $("#" + listId + " option").filter(function() {
return ($(this).val() == val);
});
var code = ($.type($option.data("code")) != "undefined" ? $option.data("code") : "");
$("#productCode").val(code);
});
});
</script>
Not completely sure if this solution could help you but with some jquery you can do this:
$('#submit').click(function()
{
var value = $('#product').val();
alert($('#productName [value="' + value + '"]').data('value'));
$('#productId').val($('#productName [value="' + value + '"]').data('value'));
//after this line the form should submit and correct value passes to server but value passes through hidden input
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="hidden" name="productId" id="productId" />
<input type="text" name="product" id="product" list="productName" />
<datalist id="productName">
<option value="Pen" data-value="ISB"></option>
<option value="Pencil" data-value="KHI"></option>
<option value="Paper" data-value="PWH"></option>
</datalist>
<input id="submit" type="submit">

How do I store <input> "names" as properties of an object and then store the matching <input> "value" as the values of that object's properties?

I'm looking to essentially build an object dynamically where a property be the inputs name and the value of that property will be the inputs value.
Here's HTML
<form>
<fieldset>
<legend>form</legend>
<label>First<input type="text" value="null" name="first"/></label>
<label>Last<input type="text" value="null" name="last"/></label>
<label>Email<input type="text" value="null" name="email"/></label>
<input type="submit" value="submit"/>
</fieldset>
</form>
Here's the jQuery I'm using so far.
I have stored the values in and names in separate arrays. Is there a way to create some sort of associative array or to create an object where property names are taken from one array and values taken from another?
var values = new Array();
var names = new Array();
$("form").submit(function(event){
event.preventDefault();
values = [];
names = [];
$('form input').not('[type="submit"]').each(function(){
values.push($(this).val());
});
$('form input').not('[type="submit"]').each(function(){
names.push($(this).attr("name"));
});
});
I've also tried the .serializeArray() and it returns an array of Objects. But then I have no idea how to pull all of the key/value pairs out of that object and into a new one.
The end goal is to not send this data over ajax but to send to a third party that aggregates data for analytics. Please help. I'm self taught and totally lost. Haha. Thanks
PS
I tried this
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
var input = $("form").serializeArray();
$.each(input, function(i, field){
console.log(JSON.stringify(input[i]));
});
});
but it returns this
{"name":"first","value":"null"}
{"name":"last","value":"null"}
{"name":"email","value":"null"}
which seems to be equally as unhelpful. Haha.
I would love to be able to get an outcome as such
{
"first" : "null",
"last" : "null",
"email" : "null"
}
Easiest way I can think of is to use serializeArray and then reduce that to an object or map. For example
$('form').on('submit', e => {
e.preventDefault();
let values = $(this).serializeArray().reduce((map, input) => {
let value;
if (map.hasOwnProperty(input.name)) {
value = Array.isArray(map[input.name]) ?
map[input.name] : [map[input.name]];
value.push(input.value);
} else {
value = input.value;
}
map[input.name] = value;
return map;
}, {});
})
This handles <select multiple> and <input type="checkbox"> elements by setting the named value as an array.
JSFiddle demo here ~ https://jsfiddle.net/wmjeh5Lv/1/
Legacy version
$('form').on('submit', function(e) {
e.preventDefault();
var values = $(this).serializeArray().reduce(function(map, input) {
var value;
if (map.hasOwnProperty(input.name)) {
value = Array.isArray(map[input.name]) ?
map[input.name] : [map[input.name]];
value.push(input.value);
} else {
value = input.value;
}
map[input.name] = value;
return map;
}, {});
})
This should work, though realistically I don't understand the need for it. Check your browser's console. It gave me:
{first: "null", last: "null", email: "null"}
$(document).ready(function() {
$('form').on('submit', function(e) {
e.preventDefault();
var arrObj = {};
$(this).find('input:not(:submit)').each(function(i, el) {
el = $(el);
arrObj[el.attr('name')] = el.val();
});
console.log(arrObj);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<fieldset>
<legend>form</legend>
<label>First
<input type="text" value="null" name="first" />
</label>
<label>Last
<input type="text" value="null" name="last" />
</label>
<label>Email
<input type="text" value="null" name="email" />
</label>
<input type="submit" value="submit" />
</fieldset>
</form>
<div id="results">
</div>
Quick bit about Scope and Functions
Note: I am not a javascript expert, I have no formal education on it these are simply the things I've learned in using javascript.
If you define a variable outside a function, you can use it inside*
Using the same code I gave you, you could do something like this:
$(document).ready(function() {
var arrObj = {};
//Notice, arrObj is now defined OUTSIDE of our form.onsubmit function
$('form').on('submit', function(e) {
e.preventDefault();
$(this).find('input:not(:submit)').each(function(i, el) {
el = $(el);
arrObj[el.attr('name')] = el.val();
});
console.log(arrObj);
});
$('button').on('click', function() {
console.log(arrObj);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<fieldset>
<legend>form</legend>
<label>First
<input type="text" value="null" name="first" />
</label>
<label>Last
<input type="text" value="null" name="last" />
</label>
<label>Email
<input type="text" value="null" name="email" />
</label>
<input type="submit" value="submit" />
</fieldset>
</form>
<button>Click me and Check Console<small>*Must click submit button first</small></button>
This goes up as far as you want it to.
Got a variable you defined outside the $(document).ready(...) and you want to use it? Go ahead. Javascript don't care.
When in doubt, create another function that you can return from somewhere else, like so (this involves using $.fn.extend() to add a new method to every jquery object)
$.fn.extend({
formObject: function() {
var arrObj = {};
$(this).find('input:not(:submit)').each(function(i, el) {
el = $(el);
arrObj[el.attr('name')] = el.val();
});
return arrObj;
}
});
$(document).ready(function() {
$('button').on('click', function() {
alert('check console');
console.log($('form').formObject());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<fieldset>
<legend>form</legend>
<label>First
<input type="text" value="null" name="first" />
</label>
<label>Last
<input type="text" value="null" name="last" />
</label>
<label>Email
<input type="text" value="null" name="email" />
</label>
</fieldset>
</form>
<button>Click Me</button>
These are not the only ways, and if I am honest I don't even think they're the best ways, but they're the fastest ways using what we already have.
I don't understand why the submit button if the only need it go generate an object?
So here is my try only to generate the output without arrays ...
function generate() {
var obj = {};
$('form input').not('[type="submit"]')
.each((index, input) => obj[input.name] = input.value);
$('#result').text(JSON.stringify(obj));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<form>
<fieldset>
<legend>form</legend>
<label>First<input type="text" value="null" name="first"/></label>
<label>Last<input type="text" value="null" name="last"/></label>
<label>Email<input type="text" value="null" name="email"/></label>
<button onclick="generate()">Generate</button>
</fieldset>
</form>
<br>
<div id="result"></div>

Populate an input with the contents of a custom option (data-) attribute

In the example below, I'm trying to populate an input with the contents of the option.data-foo attribute. I feel like this close... but I've got something back-to-front somewhere... Any thoughts?
My code :
function updateText(type) {
var id = type+'Text';
document.getElementById(id).data-foo = document.getElementById(type).value;
}
<form id="example" name="example">
<select id="sensor" onchange="updateText('sensor')">
<option value="Jval" data-foo="Jfoo">Joption</option>
<option value="Kval" data-foo="Kfoo">Koption</option>
</select>
<br />
<input type="text" value="" id="sensorText" />
</form>
If you're using jQuery then use this:
$('#sensor').change(function() {
$('#sensorText').val( $(this).find('option:selected').data('foo') )
})
$('#sensor').change(function() {
$('#sensorText').val( $(this).find('option:selected').data('foo') )
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="example" name="example">
<select id="sensor">
<option value="Jval" data-foo="Jfoo">Joption</option>
<option value="Kval" data-foo="Kfoo">Koption</option>
</select>
<br />
<input type="text" value="" id="sensorText" />
</form>
What you're going for, is probably this :
var selectField = document.getElementById('sensor');
var textField = document.getElementById('sensorText');
var updateTextField = function() {
textField.setAttribute(
'value',
selectField.options[selectField.selectedIndex].dataset.foo
);
}
// Populate your text field when loading your page
updateTextField();
// Update your text field when an option is selected
selectField.addEventListener('change', updateTextField);
<form id="example" name="example">
<select id="sensor">
<option value="Jval" data-foo="Jfoo">Joption</option>
<option value="Kval" data-foo="Kfoo">Koption</option>
</select>
<br />
<input type="text" value="" id="sensorText" />
</form>
(see also this Fiddle)
You can also resolve it in this way
$("#sensor").on("change", function(){
var $selectedItem = $(this).find(":selected");
var dataValue = $selectedItem.data("foo");
$("#sensorText").val(dataValue);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="example" name="example">
<select id="sensor">
<option value="Jval" data-foo="Jfoo">Joption</option>
<option value="Kval" data-foo="Kfoo">Koption</option>
</select>
<br />
<input type="text" value="" id="sensorText" />
</form>
if you are using jquery:
var value = $('#elementId').attr('data-foo');

How to auto Set input values in a form when select an option?

I have a form for example:
<form>
<ul>
<li>
<select name="choose">
<option value="0">1</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</li>
<li><h2>No. Of person</h2></li>
<input type="text" name="ref_person"id="field" value="" />
<li><h2>earning of person:</h2></li>
<input type="text" name="ear_person" id="field" value="" />
</ul>
</form>
so, when I choose option:1 both the input fields must be filled with no. let say, No. of person = 3 and earning of person = $5.
Your question should be as well written as you can make it, including valid, semantic HTML.
Also, a question should contain the code you have tried, an explanation of what you have tried, where it's going wrong and exactly what you expect it to do, including some example input and output.
The following may help. Note that element IDs must be unique and that forms should use semantic markup (e.g. don't use a list to present it, don't put headings inside lists, use labels, group elements using fieldsets, etc.).
You can use the select element's change event to get the value and text of the selected option and display it elsewhere in the form. You can also reference form controls as named properties of the form, which is handy and more straight forward than using getElementById.
In the code, a reference to the select is passed to the function using this. Every form control has a form property that is a reference to the form that it's in. The rest should be easy enough to understand, but please ask if you need other help.
function getPerson(select) {
var form = select.form;
form.ref_person.value = select.options[select.selectedIndex].text;
form.ear_person.value = select.value;
}
<form>
<fieldset><legend>Person and earning</legend>
<label for="personSelect">Select a person
<select name="choose" id="personSelect" onchange="getPerson(this)">
<option value="0">1</option>
<option value="100">2</option>
<option value="500">3</option>
</select>
</label>
<br>
<label for="personNumber">No. Of person:
<input type="text" name="ref_person"id="personNumber"></label>
<label for="personEarning">Earning of person:
<input type="text" name="ear_person" id="personEarning"></label>
</fieldset>
</form>
function getPerson(select) {
var form = select.form;
form.ref_person.value = select.options[select.selectedIndex].getAttribute('per');
form.ear_person.value = select.value;
}
<form>
<fieldset><legend>Person and earning</legend>
<label for="personSelect">Select a person
<select name="choose" id="personSelect" onchange="getPerson(this)">
<option per="3" value="0">1</option>
<option per="9" value="100">2</option>
<option per="27" value="500">3</option>
</select>
</label>
<br>
<label for="personNumber">No. Of person:
<input type="text" name="ref_person"id="personNumber"></label>
<label for="personEarning">Earning of person:
<input type="text" name="ear_person" id="personEarning"></label>
</fieldset>
</form>
Here is a code sample that uses the onchange event to copy values to the textboxes.
<script type="text/javascript">
function selectOnChange(obj) {
var val = obj.options[obj.selectedIndex].value;
var text = obj.options[obj.selectedIndex].text;
document.getElementById("field1").value = val;
document.getElementById("field2").value = text;
}
</script>
</head>
<body>
<div>
<select onchange='selectOnChange(this)' name="choose">
<option value="100">1</option>
<option value="200">2</option>
<option value="300">3</option>
</select>
</div>
<ul><li><h2>No. Of person</h2></li></ul>
<div>
<input type="text" name="ref_person" id="field1" value="">
<ul>
<li><h2>earning of person:</h2></li></ul>
<input type="text" name="ear_person" id="field2" value="" />
</div>
I couldn't get a switch statement to work, so I did it with three if statements, but here is my solution. Fiddle with it yourself to make it as you wish.
<form>
<ul>
<li>
<select name="choose" id="option1" onchange="relatedPrice()">
<option value="0">1</option>
<option value="1">2</option>
<option value="2">3</option>
</select>
</li>
<li><h2>No. Of person</h2></li>
<input type="text" name="ref_person" id="field1" value="" />
<li><h2>earning of person:</h2></li>
<input type="text" name="ear_person" id="field2" value="" />
</ul>
</form>
<script>
function relatedPrice() {
var e = document.getElementById("option1");
var test = e.options[e.selectedIndex].text;
document.getElementById("field1").value = test;
if(test==1) {
document.getElementById("field2").value = 100;
}
if(test==2) {
document.getElementById("field2").value = 200;
}
if(test==3) {
document.getElementById("field2").value = 300;
}
}
</script>

Synchronize multiple value retrievals in jquery

I have 3 inputs in the the DOM with id a, b, and c - containing numbers - and a javascript function:
function func(a,b,c)
{
console.log(a+b+c);
}
I want to call func when any of these 3 inputs refreshes, by taking the value of the two others. For the moment, I am proceding this way:
<script>
function func(a,b,c)
{
console.log(a+b+c));
}
$(function(){
$('#a').on('change', function(){
func(this.value, $('#b').val(), $('#c').val())
});
$('#b').on('change', function(){
func($('#a').val(), this.value, $('#c').val())
});
$('#c').on('change', function(){
func($('#a').val(), $('#b').val(), this.value)
});
});
</script>
But this appraoch does not seem elegant, particularly if there is a lot of inputs (we could imagine 2 or 3 more inputs with ids d, e ..). Would there be a more concise approach in such case?
You could do something simple with a CSS class like this:
$('.myInputs').on('change', function() {
var a = $('#a').val();
var b = $('#b').val();
var c = $('#c').val();
func(a, b, c);
});
but don't forget to add the class to your inputs
You can have similar class to every input and calculate it's amount by $.each
<script>
$(function () {
$('.calculate').on('change', function () {
var result = "";
$.each($('.calculate'), function () {
result += $(this).val();
});
console.log(result);
});
});
</script>
<input type="text" name="a" id="a" class="calculate" />
<input type="text" name="b" id="b" class="calculate" />
<input type="text" name="c" id="c" class="calculate" />
<input type="text" name="d" id="d" class="calculate" />
I can suggest:
Have a single event handler and a single selector.
Pass array of values into a function.
function func(vals) {
console.log(vals.reduce(function(a, b) {
return a + b;
}, 0));
}
$(function() {
var $els = $('#a, #b, #c'); // better to use a common class
$els.on('change', function() {
var vals = [];
$.each($els, function(_, item) {
vals.push(parseInt(item.value, 10));
});
func(vals);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="a">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select id="b">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select id="c">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
By giving similar/unique class to required textfield and using $.each you can generalize the code as per your requirement.
$(document).ready(function(){
$('.mynumberfield').on('change', function(){
func();
});
function func()
{
var total = 0;
$('.mynumberfield').each(function(){
var currVal = $(this).val();
if($.trim(currVal).length>0 && !isNaN(currVal))
{
currVal = parseFloat(currVal);
total +=currVal;
}
});
$("#total").text(total);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
a<input type=text class="mynumberfield" id="a" />
b<input type=text class="mynumberfield" id="b" />
c<input type=text class="mynumberfield" id="c" />
d<input type=text class="mynumberfield" id="d" />
e<input type=text class="mynumberfield" id="e" />
f<input type=text class="mynumberfield" id="f" />
g<input type=text class="mynumberfield" id="g" />
Total:<p id="total"></p>
The problem I find with the above solutions is that they require you in one way or another to keep track of the inputs. This is not scalable. Here is a solution that is more scalable (only requiring you to remember to add a class on the inputs you want included in the calculation/concatenation)
Firstly let's deal with your selector:
1: If say your inputs are of type "text" and all of the fields in your DOM of type "text" are to be considered in your calculation then your selector can be:
$("input[type=text]")
2: If the above is not the case then set a class on all of the inputs that you want included in the calculation. Then after having added the class (let's say "my_class" for our example) on all of the relevant inputs your selector will be:
$(".my_class")
So now that we have the selector let's deal with the function:
function func($selector)
{
var allValues = "";
$selector.each(function(){
allValues += $(this).value();
})
console.log(allValues);
}
And if you are not concatenating string values but adding numbers then:
function func($selector)
{
var allValues = 0;
$selector.each(function(){
var value = $(this).value().trim();
allValues += ($(this).value().length>0 && !isNaN(value)) ? parseInt(value) : 0;
})
console.log(allValues);
}
You would then call this function depending on what your selector is by any of the two:
func($("input[type=text]"));
//OR
func($(".my_class"))
Hope I did not miss anything. If I did not understand your question well then say and I will try to adjust my answer accordingly

Categories

Resources