I have made a small calculator, where I want the sum in to be displayed with the format currency in the readonly input text.
Since I'm new to javascript (and this forum), I can't get it to work.
Thought my code below would work. Can anyone give me some pointers on how to make it work?
<h2>Calculator/h2>
<input
type="text"
id="number1"
value="0"
onchange="summa.value = (number1.value*1) + (number2.value*1)"
/>
<br>
<input
type="text"
id="number2"
value="0"
onchange="summa.value = (number1.value*1) + (number2.value*1)"
/>
<br/><br/>
<input
type="text"
readonly="readonly"
id="summa"
value="0"
onchange="this.value.toLocaleString("sv-SE", {
style:"currency",
currency:"SEK",
currencyDisplay:"symbol",
maximumFractionDigits: 0
});"
/>
Your code as posted shows quite a few typos, but the main reason it 'doesn't work' is that programatic changes to an input don't trigger a change event. It will be far clearer to abstract your methods into its own script and then appropriately handle the changes and update the total.
Here is a minimal example of your logic abstracted into html and a separate script. The inputs have been changed to type="number" to avoid entering non-numeric values. The script then queries the three inputs using getElementById and attaches change listeners to the two accepting input using addEventListener. Finally there is a single function declared to update the value of the third input with the formatted value.
const number1 = document.getElementById('number1');
const number2 = document.getElementById('number2');
const summa = document.getElementById('summa');
function updateTotal() {
const total = Number(number1.value) + Number(number2.value);
summa.value = total.toLocaleString('sv-SE', {
style: 'currency',
currency: 'SEK',
currencyDisplay: 'symbol',
maximumFractionDigits: 0,
});
}
number1.addEventListener('change', updateTotal);
number2.addEventListener('change', updateTotal);
<h2>Calculator</h2>
<input type="number" id="number1" value="0"/>
<br />
<input type="number" id="number2" value="0" />
<br />
<input type="text" id="summa" readonly="true" value="0"/>
note: your method of coercing a string to number is valid, but there are more transparent methods. Here I'm using the Number constructor directly but there are plenty of other methods
If you somehow feel that you need to do this all inline you can apply the same logic, but you'll instantly note the amount of duplicated code.
<h2>Calculator</h2>
<input type="number" id="number1" value="0" onchange="summa.value = (Number(number1.value) + Number(number2.value)).toLocaleString('sv-SE', {
style: 'currency',
currency: 'SEK',
currencyDisplay: 'symbol',
maximumFractionDigits: 0,
});" />
<br />
<input type="number" id="number2" value="0" onchange="summa.value = (Number(number1.value) + Number(number2.value)).toLocaleString('sv-SE', {
style: 'currency',
currency: 'SEK',
currencyDisplay: 'symbol',
maximumFractionDigits: 0,
});" />
<br />
<input type="text" readonly="readonly" id="summa" value="0" />
Alternatively you can include an inline script as a decent compromise.
<h2>Calculator</h2>
<input type="number" id="number1" value="0" />
<br />
<input type="number" id="number2" value="0" />
<br />
<input type="text" id="summa" readonly="true" value="0" />
<script type="module">
const number1 = document.getElementById('number1');
const number2 = document.getElementById('number2');
const summa = document.getElementById('summa');
function updateTotal() {
const total = Number(number1.value) + Number(number2.value);
summa.value = total.toLocaleString('sv-SE', {
style: 'currency',
currency: 'SEK',
currencyDisplay: 'symbol',
maximumFractionDigits: 0,
});
}
number1.addEventListener('change', updateTotal);
number2.addEventListener('change', updateTotal);
</script>
Related
Is it possible to add a decimal on a number input, as a user types?
I have the below input:
<div class="form-control">
<label for="bill">Bill</label>
<input
type="number"
id="bill"
name="bill"
placeholder="0"
maxlength="6"
/>
And I want it to look like the below as I type:
I've tried to set the input.value and wrap it in formatter.format(), using the below, but I get a parsing error. Because of the $ sign and it being a number input, I'm guessing.
let formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD', });
Is there anyway to do this?
Use regex to remove non digits, then add the decimal using string function.
document.getElementById('bill').addEventListener('input', function(){
if(this.value.length > 2){
var val = this.value.replace(/[^\d]/, '');
val = val.substr(0, val.length-2)+"."+val.substr(-2);
this.value = val;
}
});
<input
type="number"
id="bill"
name="bill"
placeholder="0"
maxlength="6"
/>
Inside a Vue-component, I'm making a list, but the number of entries in the list varies.
So it could be like this:
<form>
<input type="number" value="15" />
<input type="number" value="10" />
<input type="number" value="5" />
<input name="total" :value="summedTotal" /> <!-- (calculated dynamically) -->
</form>
Or like this:
<form>
<input type="number" value="15" />
<input type="number" value="10" />
<input type="number" value="5" />
<input type="number" value="17" />
<input type="number" value="20" />
<input name="total" :value="summedTotal" /> <!-- (calculated dynamically) -->
</form>
If I had a fixed set of input fields, then I would have solved it using v-model. But now the number of 'models' are dynamic.
Can I somehow still use v-model to solve this?
Currently I'm adding an #keypress-event, finding the input ( document.getElementById( '....' ) and finding the value from that. But I need to set a delay for it to work. I could use keyup or some other event-watcher, but it all becomes really hacky, really quick.
The actual code is (an advanced version of) this:
<form>
<input
type="number"
v-for="(entry, index) in list"
name="entry.id"
value="entry.initial_value"
:id="'entry-id__' + entry.id" #keypress="calculateSum()"
/>
<input name="total" :value="summedTotal" /> <!-- (calculated dynamically) -->
</form>
You should be able to use a v-model that will allow your input fields to change the value in the list :
<input
type="number"
v-for="(entry, index) in list"
:key="'input-field-'+entry.id"
name="entry.id"
v-model="entry.initial_value"
:id="'entry-id__' + entry.id"
/>
When a new value is set by the user, it should modify this precise value in your list object.
Then keep your last line as is:
<input name="total" :value="summedTotal" />
with summedTotal being a computed value summing the values of your list.
If you don't want to change your original list, you can make a deep copy first and then use copiedList for your v-model:
data {
copiedList : JSON.parse(JSON.stringify(this.list))
}
Here is a Snippet that works:
new Vue({
el: '#app',
data: {
list: [{
id: 1,
initial_value: 3
},
{
id: 2,
initial_value: 1
},
{
id: 3,
initial_value: 7
},
{
id: 4,
initial_value: 2
},
]
},
computed: {
summedValued() {
return this.list.reduce((acc, c) => {
return acc + parseInt(c.initial_value || 0);
}, 0)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(entry, index) in list" :key="'input-field-'+entry.id">
ID {{entry.id}}: <input type="number" name="entry.id" v-model="entry.initial_value" :id="'entry-id__' + entry.id" />
</div>
TOTAL :{{summedValued}}
</div>
jQuery, disable all others input on same class if sum of all value more than x
How to disable "HTML input box" which not empty node when the sum of any input box has value. I want to calculate some of any input field and disable any others if the sum is greater than x.
For example to this code:
second field = 5
forth field = 10,
sum is 15
first field and third field should be disabled
$('.inputReward').on('input',function() {
//$(this).next().not(this).prop('disabled', this.value.length)
var sum=0;
$('.inputReward').each(function () {
sum += +$(this).val();
if(sum>15) //15 is maximum value
$(this).next().not(this).prop('disabled', true);
else
$(this).next().not(this).prop('disabled', false);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" name="sRewards" value="" class="inputReward" />
<input type="number" name="sReward1" value="" class="inputReward" />
<input type="number" name="sReward2" value="" class="inputReward" />
<input type="number" name="sReward3" value="" class="inputReward" />
But now i just can do only disable all next input field of a last not empty node.
I think this is my best solution :)
$('.inputReward').on('input',function() {
//$(this).next().not(this).prop('disabled', this.value.length)
var sum=0;
$('.inputReward').each(function () {
sum += +$(this).val();
});
if(sum>=15)
$(this).siblings().not(this).prop('disabled', true);
else
$(this).siblings().not(this).prop('disabled', false);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" name="sRewards" value="" class="inputReward" />
<input type="number" name="sReward1" value="" class="inputReward" />
<input type="number" name="sReward2" value="" class="inputReward" />
<input type="number" name="sReward3" value="" class="inputReward" />
I am using the code below in a html form:
<input type="text" name="cars[]" required>'
Note the use of "cars[]" for the name.
This allows me to have multiple inputs with the same name.
I would like to get the answers from all the inputs in JavaScript.
How can this be done?
I have the following WRONG code for this:
var element = document.getInput("cars[]");
for (i = 0; i < element.length; i++) {
alert(element[i].value);
}
You have to use document.getElementsByName() like this:
var element = document.getElementsByName("cars[]");
for(i=0; i<element.length;i++){
alert(element[i].value);
}
<input type="text" name="cars[]" value="a" required>
<input type="text" name="cars[]" value="b" required>
<input type="text" name="cars[]" value="c" required>
These two things in pure JavaScript net approximately the same result. The first is using the HTML form element to find all of the input elements attached to it. However, the syntax for finding the array called "cars[]" is troublesome and in my opinion a tad annoying. If I was going to do something in pure JavaScript I'd probably prefer the second way, using document.querySelectorAll.
window.addEventListener('load', function() {
var form = document.getElementById('thing');
form.elements['cars[]'].forEach(function(el, i) {
console.log("value is ", el.value)
}); //Form.elements[] array has been available since Chrome 7 or so. It should be available for use in just about any browser available.
var items = document.querySelectorAll('[name="cars[]"]');
items.forEach(function(el, i) {
console.log("Item Value is ", el.value)
});
});
<form id="thing">
<input type="text" name="cars[]" value="1" />
<br />
<input type="text" name="cars[]" value="2" />
<br />
<input type="text" name="cars[]" value="3" />
<br />
<input type="text" name="cars[]" value="4" />
<br />
<input type="submit" value="submit" />
</form>
You write
Note the use of "cars[]" for the name.
This allows me to have multiple inputs with the same name.
In HTML, you can have many inputs in the same form with the same name, regardless of that name having a [] suffix or not. This has always been used for, say, checkboxes. Most server-side libraries will then return the values for those inputs as an array.
An example of gathering all values for inputs with a given name could be the following:
document.querySelector("#b").addEventListener("click", () => {
const values = [];
document.querySelectorAll("input[name='color']").forEach(e => values.push(e.value));
console.log(values); // outputs ["foo", "bar", "baz"] if values unchanged
});
input { display: block; margin: 5px; }
<label>Enter your favorite colors
<input type="text" name="color" value="foo"/>
<input type="text" name="color" value="bar"/>
<input type="text" name="color" value="baz"/>
</label>
<label>
Enter your favorite food
<input type="text" name="food" value="flub"/>
</label>
<button id="b">Click me to output favorite colors</button>
You can give same id to all inputs like
<input type="text" id="inputId" name="cars[]" required>'
In Javascript iterate the element to get the value
var element = document.getElementsByName("cars[]");
for(i=0; i<element.length;i++){
console.log(element[i].value);
}
This is frustrating!
When the input type is text and I gave maxlength as 5, it is not allowing me to enter more than 5 characters
<input type="text" maxlength="5" />
If I gave input type as number and I gave maxlength as 5, it is allowing more than 5 digits?
<input type="number" maxlength="5" pattern="[0-9]*" />
Am I missing something?
PS: This is for mobile responsive site!
Instead of maxlength use max
<input type="number" min="1" max="10000" />
Update
Small jQuery plugin
(function ($) {
$.fn.maxlength = function (length) {
return this.on('keydown', function () {
var maxlength = length || parseInt($(this).attr('maxlength'), 10) ;
if (maxlength && $(this).val().length >= maxlength) {
$(this).val($(this).val().slice(0, maxlength - 1));
}
});
};
}($));
Example
try using max...
<input type="number" max="99999" />
EDIT: Showing Validation
<form id='FormValidation'>
<input id="myNum" type="number" min="1" max="99999" />
<input type="text" maxlength="5" />
<input type="submit" />
</form>
Try adding a number greater than 99999 and hitting submit, check the updated fiddle.
This jquery could help too...
$('#myNum').keyup( function(e){
var max = $('#myNum').attr('max').length;
if ($(this).val().length >= max) {
$(this).val($(this).val().substr(0, max));
}
});
replace maxlength with max
// Max Length = 5
<input type="number" max="99999" />
// length between 1 to 5
<input type="number" min="1" max="99999" />
Updated Answer. It's so simple!
<input type="number" id="nbr"/>
<input type="text" maxlength="5" />
$(document).on('keypress','#nbr', function(e){
if($(this).val().length >= 5)
{
e.preventDefault();
}
});
And you can add a max attribute that will specify the highest possible number that you may insert
<input type="number" max="999" />
if you add both a max and a min value you can specify the range of allowed values:
<input type="number" min="1" max="999" />