Knockout.js textInput fields dependent on each other - javascript

So the user wants to buy some potato. He can either enter the amount of potato in kilograms and get total price in dollars, or he can do the reverse - enter dollars and get kilograms of potato. So there's 2 input fields.
Requirements: values must update immediately after typing. Entering value in one field updates the other, and vice versa. Kilograms must stay whole, with one exception - when user enters not whole weight himself.
Price is stored internally in cents. Price is shown to the user as dollars per 1000 kilogram. Amount in kilograms is always integer.
Here is my code:
var ViewModel = function () {
var self = this;
this.totalPrice = ko.observable();
this.pricePerKg = ko.observable(999);
this.potatoWeight = ko.computed({
read: function () {
var totalPrice = self.totalPrice();
var potatoWeight = (totalPrice * 100) / self.pricePerKg() * 1000;
return Math.round(potatoWeight);
},
write: function (potatoWeight) {
var totalPrice = (potatoWeight * self.pricePerKg()) / 100 / 1000;
self.totalPrice(totalPrice.toFixed(2));
}
});
};
ko.applyBindings(new ViewModel());
HTML:
<label for="potato">Potato, kg</label>
<input type="text" id="potato" data-bind="textInput: potatoWeight">
<label for="priceTotal">Price total, $</label>
<input type="text" id="priceTotal" data-bind="textInput: totalPrice">
<div> Price per 1000 kilogram:
<span data-bind="text: (pricePerKg() / 100).toFixed(2)">
</span>$
Jsfiddle: https://jsfiddle.net/9td7seyv/13/
Problem : when you type value in "potato weight" it updates not only value in dollars, but also itself. Because of rounding it leads to inconsistencies. Go to jsfiddle above and try to type 500 in weight field. It turns itself to 501 the moment you enter the last zero.
So is there a way to stop the field updating itself, or probably some other approach to this problem is needed?

For this case, the most straight forward way I can think of is to keep a copy of the value entered by the user after any calculation ... like in the code below.
var ViewModel = function () {
var self = this;
this.totalPrice = ko.observable();
this.pricePerKg = ko.observable(999);
this.weight=ko.observable();
this.potatoWeight = ko.computed({
read: function () {
return self.weight();
},
write: function (potatoWeight) {
var totalPrice = (potatoWeight * self.pricePerKg()) / 100 / 1000;
self.totalPrice(totalPrice.toFixed(2));
self.weight(potatoWeight);
}
});
};
ko.applyBindings(new ViewModel());
https://jsfiddle.net/9td7seyv/16/
update :
For both values
https://jsfiddle.net/9td7seyv/19/

Related

Not showing result with decimal discount value

I have a discount jquery calculator plugin.It is working. But percentage is not working with decimal values like Eg: 5.45%, 10.50% , 15.70%, 20.75% etc.. I created a Codepen project for it. Please check this Codepen link https://codepen.io/coderco/pen/gOeReMQ . Here is my codes. Please help me..
HTML
<input type="text" id="Amount" value="">
<input type="text" value="10.45" id="Discount">
<input type="text" id="Result">
Script
$(document).on("change keyup blur", "#Discount", function() {
var main = $('#Amount').val();
var disc = $('#Discount').val();
var dec = (disc / 100).toFixed(2); //its convert 10 into 0.10
var mult = main * dec; // gives the value for subtract from main value
var discont = main - mult;
$('#Result').val(discont);
});
It's because of toFixed(2). When you divide the value by 100 then there are 4 decimal places.
For example:
Amount = 100, Discount = 10.45
dec = (10.45/100) = 0.1045 (Calling toFixed(2) changes it to 0.10 that means 10 instead of 10.45).
In my suggestion add toFixed(2) to the final answer (discount), Instead of while calculating.

How to do an operation with keyup or input? javascript (jQuery)

I got a problem, I have two text fields, both have a value by default when open the page or reaload, values the I get from MySQL and PHP, like this:
<input type="text" id="field1" value="<?php echo $first_value; ?>" />
<input type="text" id="utility" value="<?php echo $second_value; ?>" />
And with javascript I would like to do that when I change the value of #field1 do a subtraction and show the result into #utility.
The problem is that the result of the operation isn't correct, for example:
if #field1 has 500 the first time and #utility 1041.00 and now if I change the value of #field1 with 1000 the new value for #utility is -69.06, I guess it is doing the operation everytime that I delete or add a new number but I have no idea how to fix this, this is my javascript (jquery) code:
$('#field1').on('input', function() {
var difference = parseFloat($(this).val());
var utility = $('#utility').val().replace(/,/g, '');
var total = utility - difference;
if (!total) { total = 0; }
$('#utility').val(parseFloat(Math.round(total * 100) / 100).toFixed(2));
});
Your other option without adding extra fields would be to use .on('blur',function(){} ) or simply .blur(function(){})
This would cause the action to take place when input left the field forcing the refresh.
I solved my problem by creating a new input field type hidden with the same value of #utility and I named it as #new_utilty
$('#field1').on('input', function() {
var difference = parseFloat($(this).val());
var utility = $('#new_utility').val().replace(/,/g, '');
var total = utility - difference;
if (!total) {
total = 0;
$('#utility').val(parseFloat(Math.round(utility * 100) / 100).toFixed(2));
} else {
$('#utility').val(parseFloat(Math.round(total * 100) / 100).toFixed(2));
}
});
And this was my solution without Ajax Call

Javascript calculation returns 'on' when calculating percentage of variable

I constructed a calculation form out of different modules and got it to work except for 1 element.
The overall calculation is build up as (value + value = total), and the values are all regular numbers.
However, the last bit I added is a 'percentage'-value which is 10% of the first value in the form. So as an example:
Value 1 = 50,
Percent value 2 = 5 (10% of value 1),
Total = 55
In my code this looks as follows:
var NonTrans_prices = new Array();
NonTrans_prices["NoneNon"] = 0;
NonTrans_prices["LemonNon"] = 5994;
NonTrans_prices["CustardNon"] = 7076;
function NonTrans() {
var NonTransPrice = 0;
var theForm = document.forms["GRANADANEO"];
var selectedFilling = theForm.elements["NonTrans"];
NonTransPrice = NonTrans_prices[selectedFilling.value];
return NonTransPrice;
}
var price = NonTrans_prices;
var percentage = 10;
var costs = (price * percentage) / 100;
var optionprice = price + percentage;
function optionprice1() {
var inscriptionPrice = 0;
var theForm = document.forms["GRANADANEO"];
var optionprice = theForm.elements["optionprice"];
if (optionprice.checked == true) {
inscriptionPrice = optionprice.value;
}
return inscriptionPrice;
}
function calculateTotal() {
var cakePrice = NonTrans() + optionprice1();
var divobj = document.getElementById('totalPrice');
divobj.style.display = 'block';
divobj.innerHTML = "Total Price: " + cakePrice + " \u20ac";
}
*The NonTransPrice is connected to a dropdown box, and the optionprice1 is connected to a checkbox.
As soon as I tick the checkbox containing the 10% value, the letters "on" are added to the total price. What's going wrong?
**Sorry forgot to post the entire code so that you guys/girls can test: https://jsfiddle.net/6a55tm4j/
For some reason it doesn't show the total value in jsfiddle, on the live website I am testing on it does so that's not really a problem I am facing live.
Live link: http://axesseurope.be/appalacarte/Calculator/axess_calculator.html
This is the HTML code containing the parts affected by the .js code:
<body onload='hideTotal()'>
<div id="wrap">
<form action="" id="GRANADANEO" onsubmit="return false;">
<div>
<div class="cont_order">
<fieldset>
<table><tr><td>
<label >NonTrans</label>
<select id="NonTrans" name='NonTrans' onchange="calculateTotal()">
<option value="NoneNon">Select Dimensions</option>
<option value="LemonNon">3,00 6,40 0,85</option>
<option value="CustardNon">3,00 7,50 0,85</option>
</select>
</td></tr></table>
<hr>
<br/>
<label>Granada Neo Opties Algemeen</label>
<p>
<input type="checkbox" id="optionprice" name='optionprice' onclick="calculateTotal()" />
<label for='optionprice' class="inlinelabel">optionprice</label>
</p>
<p>
<input type="checkbox" id="SchuifdeurVoorzijde" name='SchuifdeurVoorzijde' onclick="calculateTotal()" />
<label for='SchuifdeurVoorzijde' class="inlinelabel">Schuifdeur in voorzijde</label>
</p>
<div id="totalPrice"></div>
</fieldset>
</div>
</div>
</form>
In the end with the help of Scott Marcus this was the solution:
function optionprice1()
{
var chkOptionPrice = document.getElementById("optionprice");
var theForm = document.forms["GRANADANEO"];
var selectedFilling = theForm.elements["NonTrans"];
var lstNonTransValue = NonTrans_prices[selectedFilling.value];
var inscriptionPrice = 0;
if(optionprice.checked === true){
// Look up the price in the array that matches the dropdown list's value
var price = NonTrans_prices[selectedFilling.value];
// Do the math to calculate 10% of the original price
var percentage = 10;
inscriptionPrice = (price * percentage) / 100;
}
// finally we return the inscriptionPrice
return inscriptionPrice;
}
Checkboxes have a value of "on" when they are selected. Ensure that your checkboxes include a value attribute that contains the meaningful data they represent. For example:
<input type="checkbox" id="chkSomeId" name="chkSomeID"
value="someValueToBeWhenChecked">
This is true of radio buttons as well.
So, in your code, this line:
inscriptionPrice = optionprice.value
is most-likely accessing the value of either a checkbox or radio button that does not have an explicit value set for it, but is checked.
Also, remember that all values pulled from HTML come into JavaScript as strings, so if you need to do math with those values, you'll want to use parseInt() and parseFloat().
UPDATE: now that you have posted your HTML, I see this:
<input type="checkbox" id="optionprice" name='optionprice' onclick="calculateTotal()" />
which is exactly what I suspected. My above answer will correct the problem. That checkbox needs a value set for it.
UPDATE:
In your following code:
//Add percentage
var price = NonTrans_prices;
var percentage = 10;
var costs = (price * percentage) / 100;
var optionprice = price + percentage;
//Add percentage
function optionprice1()
{
var inscriptionPrice=0;
//Get a refernce to the form id="GRANADANEO"
var theForm = document.forms["GRANADANEO"];
//Get a reference to the checkbox id="optionprice"
var optionprice = theForm.elements["optionprice"];
//If they checked the box set inscriptionPrice to 20
if(optionprice.checked==true){
inscriptionPrice=optionprice.value;
}
//finally we return the inscriptionPrice
return inscriptionPrice;
}
I think that you should take the 4 var lines and include them in the function.
I think that the first line: var price = NonTrans_prices; is incorrect, because it sets the variable price to the actual array of NonTrans prices, rather than looking up a particular price, which would be:
var price = NonTrans_prices[document.getElementById("nonTransList").value];
Then, your problem is that if the optionPrice checkbox is checked, you are trying to access the value of the checkbox, which (as I've said) doesn't explicitly exist, so you get "on" (because the checkbox is checked). What you should be doing is setting the price to result of the 10% calculation that was just done on the line above. So the final function looks like this:
function optionprice1()
{
var chkOptionPrice = document.getElementById("optionprice");
var lstNonTransValue = document.getElementById(NonTrans).value;
var inscriptionPrice = 0;
if(optionprice.checked === true){
// Look up the price in the array that matches the dropdown list's value
var price = NonTrans_prices[lstNonTransValue];
// Do the math to calculate 10% of the original price
var percentage = 10;
inscriptionPrice = (price * percentage) / 100;;
}
// finally we return the inscriptionPrice
return inscriptionPrice;
}
You were close, but the thing that, I think, tripped you up was that you created a variable with the same name as your checkbox and after doing the calculation, you should have been trying to get the value of your variable, but you were trying to get the value of the checkbox, which isn't where the answer was.
I hope that I've understood what you wanted correctly, but even if my algorithm is off, I hope you can see that you don't want to be using the value of the checkbox to get your answer, since it doesn't store any value.

Update input in real-time with jQuery

I'm creating a script for percentage calculation on my e-commerce, but I have a problem.
I want price update in real time as I write the percentage in the field.
So I made this:
<input type="text" name="cost" onchange="disc()">
<input type="text" name="discount" id="prized" onchange="updateInput()">
<input type="text" name="price" value="">
<script>
function updateInput(){
var discount = document.getElementsByName("discount")[0].value;
var cost = document.getElementsByName("cost")[0].value;
document.getElementsByName("price")[0].value = cost - (cost * (discount / 100));
}
function disc(){
if($("#prized").val().length > 1) {
var discount = document.getElementsByName("discount")[0].value;
var cost = document.getElementsByName("cost")[0].value;
document.getElementsByName("price")[0].value = cost - (cost * (discount / 100));
}
}
<script>
But it does not work as I would like...
It does not update in real time, for "onchange".
So I did some research, and I found an interesting function: .keydown()
I have no idea how to use it in my script.
Someone can help me reach my goal?
Changing onchange by oninput should give you de behaviour you are looking for, the following snippet works for me:
function updateInput() {
var discount = document.getElementsByName("discount")[0].value;
var cost = document.getElementsByName("cost")[0].value;
document.getElementsByName("price")[0].value = cost - (cost * (discount / 100));
}
function disc() {
console.log(document.getElementsByName("discount")[0].value);
if($("#prized").val().length > 1) {
var discount = document.getElementsByName("discount")[0].value;
var cost = document.getElementsByName("cost")[0].value;
document.getElementsByName("price")[0].value = cost - (cost * (discount / 100));
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="cost" oninput="disc()"> <br><br>
<input type="text" name="discount" id="prized" oninput="updateInput()">
<input type="text" name="price" value="">
Couple of things: There's no need to use getElementBy* when using jQuery, there's no need to write the same function twice.
On input (rather than change or keyup) of both fields, run the function
$(function(){
$('#prized, #cost').on('input', function(){
var discount = $('#prized').val();
var cost = $('#cost').val();
var price = cost - (cost * (discount / 100));
$('#price').val(price);
})
});
https://jsfiddle.net/popnoodles/npgvmLkc/2/
I see 2 errors here:
First, you are not converting the values of the input fields to numbers; use parseInt() for this.
Second, declare your number inputs as such using ´type="number"´. This increases usability, as you will see.
Answer to your question:
If you use parseInt() in updateInput() and use onkeyup="updateInput" (or even better onkeypress="updateInput()" this should work. See this jsfiddle: http://jsfiddle.net/da5d92bk/
$("input[name='discount']").bind('input propertychange', function() {
//do your update here
}
Just try to use keyup listener like below.
$(document).ready(function() {
var copyField = $('#copyvalue'); //field where you want to copy
$('input[type="text"]').keyup(function() {
if($(this).val() != '') {
copyField.val($(this).val());
}
});
});
$('#idofelement').keydown(function() {
...
});

Format Numbers in JavaScript

I have a web page that allows a user to enter values into fields. When a user updates a field, I want to automatically update the total displayed to the user. Because the input fields are dynamically generated, I created a JavaScript function called "update". A sample of my code is shown here:
<input type="text" id="myField1" onchange="return update(this);" />
<input type="text" id="myField2" onchange="return update(this);" />
<span id="totalCount"></span>
var total = 0;
function update(e) {
var v = $(e).val();
if (parseInt(v) != NaN) {
total = total + v;
$("#totalCount").html(total);
}
return false;
}
When a user enters "2" into "myField1", "02" is displayed in the "totalCount" element. In reality, I would like to just display "2". How do I do this in JavaScript while taking into a account odd entries?
Thanks!
Since $(e).val() is a string, total + v is a string too. Use parseInt not just for the test but also when using the value:
var v = parseInt($(e).val(), 10);
if (!isNaN(v)) {
total = total + v;
$("#totalCount").html(total);
}

Categories

Resources