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
Related
I have just started with programming, so the answer may be obvious. My code has a radio button (price of a service) and a dropdown menu (quantity of orders), i want to calculate with these values. So far so good, it took me almost a day to get this short code.
My problem is now, I need the result to be shown realtime, possibly in an input tag like
<p><strong>Amount (US$)</strong>: <input type="text" name="amount" id="amount" /></p>
Maybe there is also a better way?
So, one of the two radio buttons should always be checked and show its price. When the user chooses the quantity from the dropdown menu, the result should automatically refresh.
Can anyone help me?
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<label>ABC
<input class="test" type="radio" checked="checked" name="test" value="500">
</label>
<label>DEF
<input class="test" type="radio" name="test" value="800">
</label>
<select size="1" name="dropdown" onchange='calculate(this.value);'>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<p><strong>Amount (US$)</strong>: <input type="text" name="amount" id="amount" /></p>
</body>
Thx for your help!
edit: Ok, even the calculation is wrong. I want to get the value of a checked radio button and turn it into an int. After this I need the int to be multiplied with the value from the checkbox. I dont know what I am missing, but its always calculating with the first radio button value, even if I check the second one.
<script>
var x = $('input[name="test"]:checked').val();
var xInt = parseInt(x, 10);
function calculate (val) {
var result = val * xInt ;
var amountPrint = document.getElementById('amount');
amountPrint.value = result;
}
$(".test").click(function(event) {
var total = 0;
$(".test:checked").each(function() {
total += parseInt($(this).val());
});
if (total == 0) {
$('#amount').val('');
} else {
$('#amount').val(total);
}
});
</script>
I still got the problem, that I need the results to be shown realtime, depending which radio button and dropdown value is checked. So I added a class "test" to the radio buttons and added the above function. Now I got the result in realtime, depending on the checked radio button, but the calculation is still wrong and i need to combine it somehow.
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<label>ABC
<input type="radio" checked="checked" name="test" value="500">
</label>
<label>DEF
<input type="radio" name="test" value="800">
</label>
<select size="1" name="dropdown" onchange='calculate(this.value);'>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<p><strong>Amount (US$)</strong>: <input type="text" name="amount" id="amount" value="" /></p>
</body>
<script>
var x = $('input[name="test"]:checked').val();
var xInt = parseInt(x, 10);
function calculate (val) {
var result = val * xInt ;
var amountPrint = document.getElementById('amount');
amountPrint.value = result;
}
</script>
You just need to push a new value to the amount area.
All I have done is added a value="" to the Amount input, which could be skipped but it is good practice IMO.
Then in the js beneath. Get the element by id which you provided earlier.
Then use your calculation, and with that tell it to change the value of id 'amount'
You could also add <p id='printResultsHere'></p> for example and call in much the same way.
I hope this helps. Please mark answer as accepted if so.
Based off the comments above
To convert strings to int use parseInt() as for to detecting change you need to detect to the radio buttons. Now you can go through and add onChange = or onClick = to all of them manually. With two why not but if you intend on having more and they will all change the outcome. You could just loop through them.
Add this to the bottom of the code
//Loop through the radio buttons, first find all the elements with that Name then you can
//loop through to to detect the onClick.
var radios = document.getElementsByName('test')
for (var i = 0, max = radios.length; i < max; i++) {
radios[i].onclick = function () {
console.log(parseInt(this.value));
}
}
You may need to rewrite the code a bit differently, as you are dealing with two varaiblies into the code but your function is only accepting one.
So to avoid doing another loop, easier to just give it an Id and go forward. So now everytime you change the check boxes it will re run the code with whatever the current value from dropdown is.
The below does what I think you want.
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<label>ABC
<input type="radio" checked="checked" name="test" value="500">
</label>
<label>DEF
<input type="radio" name="test" value="800">
</label>
<select size="1" id='dropdown' name="dropdown" onchange='calculate(this.value);'>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<p><strong>Amount (US$)</strong>: <input type="text" name="amount" id="amount" value="" /></p>
</body>
<script>
var x = $('input[name="test"]:checked').val();
var xInt = parseInt(x, 10);
//Get the input Box you want to print to
var amountPrint = document.getElementById('amount');
//All the radio boxes which you named test
var radios = document.getElementsByName('test')
function calculate(val) {
var result = val * xInt;
//var amountPrint = document.getElementById('amount');
amountPrint.value = result;
}
var radios = document.getElementsByName('test')
for (var i = 0, max = radios.length; i < max; i++) {
radios[i].onclick = function () {
xInt = parseInt(this.value, 10)
calculate(document.getElementById('dropdown').value)
}
}
</script>
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>
I'm trying to add the values of any checked checkbox to an input text field.
Here's my fiddle: http://jsfiddle.net/Lf6ky/
$(document).ready(function() {
$(":checkbox").on('click', function() {
if ($(':checkbox:checked')) {
var fields = $(":checkbox").val();
jQuery.each(fields, function(i, field) {
$('#field_results').val($('#field_results').val() + field.value + " ");
});
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input type="text" id="field_results" /><br>
<input type="checkbox" value="1">1<br>
<input type="checkbox" value="2">2<br>
<input type="checkbox" value="3">3
In this example, I have 3 checkboxes, with the values 1,2,3. If I click on all these checkboxes, then the input field should look like this: 1 2 3
If I uncheck any of these checkboxes, then that corresponding value should disappear in the input field.
How do I do this?
I've stored the collection of check-boxes in a variable $checks, then attach the handler to this collection. Inside the event handler, I take the collection once again and filter (return) only the check-boxes that are checked.
map() returns a jQuery object containing the values of the checked check-boxes, get() converts it to a standard array. Join those values with a space and put 'em in the input.
$(document).ready(function(){
$checks = $(":checkbox");
$checks.on('change', function() {
var string = $checks.filter(":checked").map(function(i,v){
return this.value;
}).get().join(" ");
$('#field_results').val(string);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="field_results"/><br>
<input type="checkbox" value="1">1<br>
<input type="checkbox" value="2">2<br>
<input type="checkbox" value="3">3
On click of a checkbox, loop through the checked inputs, append to a string then assign that to your text box:
$(document).ready(function() {
$("input:checkbox").click(function() {
var output = "";
$("input:checked").each(function() {
output += $(this).val() + " ";
});
$("#field_results").val(output.trim());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input type="text" id="field_results" /><br>
<input type="checkbox" value="1">1<br>
<input type="checkbox" value="2">2<br>
<input type="checkbox" value="3">3
First issue is
if($(':checkbox:checked')) {
will always be true since it returns a jQuery object and an object is a truthy value. If you were to use the if, you want to check the length. aka if($(':checkbox:checked').length) {
Secondly
var fields = $(":checkbox").val();
returns only the first element's value and it returns any checkbox, not just the checked ones. You want to loop through $(':checkbox:checked')
One way to attack it is to use an each and an array.
$(":checkbox").on('change', function() {
var total = [];
$(':checkbox:checked').each( function(){ //find the checked checkboxes and loop through them
total.push(this.value); //add the values to the array
});
$('#field_results').val(total.join(" ")); //join the array
});
Problem
if($(':checkbox:checked')) will always be true
var fields = $(":checkbox").val(); Will give first checkbox value
You can try this.
$(document).ready(function() {
$(":checkbox").on('click', function() {
var fields = '';
$(":checkbox").each(function() {
if (this.checked) {
fields += $(this).val() + ' ';
}
});
$('#field_results').val($.trim(fields))
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<input type="text" id="field_results" />
<br>
<input type="checkbox" value="1">1
<br>
<input type="checkbox" value="2">2
<br>
<input type="checkbox" value="3">3
I have a checkbox at the end of 5 inputs and one dropdown. I am trying through jquery to set all the inputs and the dropdown before the checkbox to 0.
There will be many employees listed so it has to be only the ones before the checkbox.
My feeble attempt at the jquery. I have the .on as sometimes it will be called through ajax
$(document).ready(function () {
$(document).on('click', '.fasCheck', function(){
if ($(this).attr("checked") == "checked"){
$(this).prev().parent().prev(".payWeek").next('input').prop('checked', true);;
} else {
}
});
});
The html:
<div class="returns" id="employee">
<h3>David Wilson</h3>
<div class="payWeek">
<label for="MonthlyReturn0PayWeek1">Pay Week1</label>
<input type="number" id="MonthlyReturn0PayWeek1" value="" maxlength="12" step="any" name="data[MonthlyReturn][0][pay_week1]">
</div>
<div class="payWeek">
<label for="MonthlyReturn0PayWeek2">Pay Week2</label>
<input type="number" id="MonthlyReturn0PayWeek2" value="" maxlength="12" step="any" name="data[MonthlyReturn][0][pay_week2]">
</div>
<div class="payWeek">
<label for="MonthlyReturn0PayWeek3">Pay Week3</label>
<input type="number" id="MonthlyReturn0PayWeek3" value="" maxlength="12" step="any" name="data[MonthlyReturn][0][pay_week3]">
</div>
<div class="payWeek">
<label for="MonthlyReturn0PayWeek4">Pay Week4</label>
<input type="number" id="MonthlyReturn0PayWeek4" value="" maxlength="12" step="any" name="data[MonthlyReturn][0][pay_week4]">
</div>
<div class="payWeek">
<label for="MonthlyReturn0PayWeek5">Pay Week5</label>
<input type="number" id="MonthlyReturn0PayWeek5" value="" maxlength="12" step="any" name="data[MonthlyReturn][0][pay_week5]">
</div>
<div class="payWeek">
<label for="MonthlyReturn0PayWeeks">Pay Weeks</label>
<select id="MonthlyReturn0PayWeeks" name="data[MonthlyReturn][0][pay_weeks]">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option selected="selected" value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div class="payWeek">
<label for="FAS">FAS</label>
<input type="checkbox" class="fasCheck" name="FAS">
</div>
</div>
$(this).attr("checked") == "checked" won't work, you already know to use .prop(). Or just use this.cecked without any jQuery.
.prev().parent() - the prev is absolutely unnecessary, all siblings do have the same parent node.
.prev(".payWeek") - seems like you want to use .prevAll() instead.
.next('input') - you don't want to find the next sibling, but a descendant. Use .children() or .find().
.prop('checked') - while appropriate for checkboxes, you have number inputs here and need to set their value, via .val().
So change it to
$(document).ready(function() {
$(document).on('click', '.fasCheck', function() {
if (this.checked) {
$(this)
.parent()
.prevAll(".payWeek")
.find('input')
.val('0');
}
});
});
From the clicked checkbox, find the closest payWeek, then select all previous payWeeks, and find all inputs within those payWeeks and set the value to zero :
$(document).ready(function () {
$(document).on('click', '.fasCheck', function(){
if ( this.checked ) {
$(this).closest('.payWeek')
.prevAll('.payWeek')
.find('input')
.val('0');
} else {
}
});
});
$(document).on('click', '.fasCheck', function(){
var $this = $(this),
$parent = $(this).parents('.returns').eq(0),
$inputs = $parent.find('input');
if ($this.prop("checked")){
$inputs.val('0');
}
});
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;
};