I made a form using html.
At first I had it really simple. My input was amount, which a user would enter. I then made javascript code to calculate a dynamic price based on the user's amount input. The code is as follows:
<input class="typeahead" type="text" placeholder="Amount" name="Gift-Card Amount"/>
The javascript:
jQuery("input[name='Gift-Card Amount']").change(function () {
if (isNaN(parseFloat(this.value)) || !isFinite(this.value)) {
jQuery(this).val('');
return false;
}
var calc = parseFloat(this.value) * 0.95;
jQuery(this).parents("form").find("input[name='price']").val(calc);
});
The calculation is a constant 0.95. So I added a new input. Store name. So the user could enter the store name. The amount:
<input class="stores typeahead" type="text" placeholder="Stores" name="name"/>
And I want price to change based on both store name and amount. So I created this object:
var stores = {
"McDonalds" : .90,
"Target" : .92,
}
var storeName = jQuery(this).parents("form").find("input[name='name']").val();
console.log(stores[storeName]);
So that instead of a constant 0.95, that value can be replaced with preset values based on the store name entered. I don't know how to get those two to work together. Meaning, how do I recode the first javascript to recornize the var store values instead of 0.95?
jQuery("input[name='Gift-Card Amount']").change(function () {
var amount = parseFloat(this.value);
if (isNaN(amount) || !isFinite(amount)) {
jQuery(this).val('');
return false;
}
var storeName = jQuery(this).parents("form").find("input[name='name']").val();
if (storeName in stores) {
var calc = amount * stores[storeName];
jQuery(this).parents("form").find("input[name='price']").val(calc);
}
});
I also suggest that you change Stores from a text input to <select>. That way, you don't depend on the user spelling the store correctly, including capitalization.
<select name="name" class="storeName">
<option value="">Please select a store</option>
<option value=".90">McDonalds</option>
<option value=".92">Target</option>
</select>
Then you can use
var calc = parseFloat(jQuery(this).parents("form").find(".storeName").val());
I would do it like the following:
function calcPrice(element) {
// Use the element that called the listener to find the form
var form = element.form;
// Access form controls as named properties of the form
var amt = form["Gift-Card Amount"].value;
// Don't clear the value if it's not suitable, it's annoying
// Let the user fix it themselves
if (parseFloat(amt) != amt) {
alert("Gift card amount is not a suitable value")
}
// Set the price
form.price.value = amt * form.store.value;
}
</script>
Sample form, which has all the store values. This way, you can have a fallback where the server gets all relevant values, you aren't dependent on client side calculations..
<form>
Store:
<select name="store" onchange="calcPrice(this)">
<option value="0.90">McDonalds
<option value="0.92">Target
</select>
<br>
Gift card amount:
<input name="Gift-Card Amount" onchange="calcPrice(this)">
Price:
<input name="price" readonly>
</form>
write a little function that may return the correct value
function retrieveStoreValue(store){
return stores[store];
} // be sure stores is defined before the first call of this one
and in your change function call it
var storeName = jQuery(this).parents("form").find("input[name='name']").val();
var calc = parseFloat(this.value) * (retrieveStoreValue(storeName) );
Related
I have two input fields productName and quantity, productName field is getting populated using a barcode scanner(don't have access to code), my requirement is to detect as soon as the value gets populated in productName fields so that I can parse the value and populate the second field quantity.
<input type="text" id="productName" name="productName">
<input type="text" id="quantity" name="quantity">
Since I don't have access to code that scans the barcode and populate the productName field, there is one possibility which I think of is repeatedly checking if the field has value or not like below
myVar = setInterval(checkValue, 1000);
function checkValue(){
var productName= document.getElementById("productName");
console.log("running");
if (productName && productName.value) {
document.getElementById("quantity").value=productName.value;
clearInterval(myVar);
}
}
But I am looking for a better approach in vanilla Javascript, is there an alternate solution?
You can use onchange.
Example:
const productNameField = document.querySelector('#productName');
const quantityField = document.querySelector('#quantity');
const populateQuantityField = () => {
quantityField.value = productNameField.value;
}
productNameField.addEventListener('change', populateQuantityField);
Further Reading:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onchange
I’m looking for a way to automate a form.
Here are the details:
Extract a certain number (displayed in its html)
Do some calculations on the extracted number (percentage of that number)
Then automatically fill the remaining input fields with the result instead of typing it out.
This is a common occurrence in forms. The solution depends on what framework / libraries you're using. Assuming you're using none, here is how you might go about it:
https://jsfiddle.net/f52h1smj/1/
rough HTML:
<form>
<label for="number">Number: </label>
<input id="number" type="number" />
<br /> <br />
<label for="calculatedNumber">Calculated Number (50%): </label>
<input id="calculatedNumber" type="number" disabled="true" />
</form>
JS:
(() => {
//get the form element nodes
const $number = document.getElementById("number");
const $calculatedNumber = document.getElementById("calculatedNumber");
//add an event listen to the value you're going to use to pre calculate the other fields
$number.addEventListener("keyup", (e) => {
//it's value is available like so
const value = e.target.value;
//do some validation so that you're calculations don't throw exceptions
if (Number(value) !== 0 && !Number.isNaN(value)) {
//set the value of the other inputs to whatever you like by setting the 'value' property of the node.
$calculatedNumber.value = value / 2;
} else {
$calculatedNumber.value = null;
}
});
})();
These things become a lot simpler in frameworks like React and Angular.
I try to achieve Total of two input fields and those fields got their value dynamically from database after selecting a dropdown option. The html code and the sql query looks like below:
<select name="getData" ID="getData" onchange="getData()">
<option value="Select">Select Subscription Package</option>
<?php
$sql = "SELECT * FROM package WHERE status = 1";
$result = $connect->query($sql);
while($row = mysqli_fetch_row($result)){
echo '<option data-price="'.$row[4].'" value='.$row[0].'> '.$row[1].' </option>';
}
?>
</select>
<input type="text" id="price1" name="price1"/>
<input type="text" id="price2" name="price2"/>
<input type="text" id="totalAmount" name="totalAmount" onblur="totalCalc()">
Value of price1 & price2 changes when SELECT Option changed. Now I need to get total of these two fields by javascript. The js code is below:
<script>
function totalCalc() {
var A = document.getElementById("price1").value;
var B = document.getElementById("price2").value;
var C = A + B;
document.getElementById("totalAmount").value = C;
}
</script>
I got the total but it needs to click the total amount field. I want the calculation should be done automatically right after the first two fields got their values dynamically.
Any help is appreciated.
You should just set up change event handlers on both inputs that point to your totalCalc function and then, at the end of your getData() function, manually trigger the change event of one of the inputs.
If the code in getData is asynchronous, then the code that manually triggers the change event should be included in the success handler of the operation.
A note about the UI. If the two price fields are being auto-populated and users won't be inputting anything into them manually, disabling the fields is probably appropriate. With regards to the final total, an input there may not make sense at all - you just need to show the result, so a span element would work.
Also, inline HTML event attributes (onclick, onchange, etc.) should not be used. There are many reasons why this 20+ year old technique needs to die the death it deserves, but because so many people don't take the time to really learn JavaScript and modern best-practices, they just copy someone else's code that uses them and go on their merry way.
So, in the code below, I'm showing how to solve this problem using modern, standards-based code that follows best-practices.
// Get references to the DOM elements you'll need to work with
let a = document.getElementById("price1");
let b = document.getElementById("price2");
let total = document.getElementById("totalAmount");
let select = document.getElementById("getData");
let price1 = document.getElementById("price1");
let price2 = document.getElementById("price2");
// Set up event handlers in JavaScript, not HTML
select.addEventListener("change", getData);
price1.addEventListener("change", totalCalc);
price2.addEventListener("change", totalCalc);
function totalCalc() {
total.textContent = +a.value + +b.value;
}
function getData(){
// This is just mean to replicate what SQL does
price1.value = 15;
price2.value = 27;
// Manually trigger the change event for either one of the inputs
// If the existing code in getData is asynchronous, then this code
// should be added to the "success" callback. If not, it can just be
// placed at the end of the function as I'm showing it here.
var event = new Event('change');
price1.dispatchEvent(event);
}
<select name="getData" id="getData">
<option value="Select">Select Subscription Package</option>
<option>Data 1 from SQL</option>
<option>Data 2 from SQL</option>
<option>Data 3 from SQL</option>
</select>
<input type="text" id="price1" name="price1" disabled>
<input type="text" id="price2" name="price2" disabled>
<!-- No need to place the result in an <input> since users won't
be inputted data here. You just need to show it. -->
<span id="totalAmount"></span>
My page shows some forms with content loaded from a database. Every row will get his own <input>. The ID of this input is equal for every row, except for the number that is attached to it, to make it unique. To make it more clear; this is how the form looks like when it loads 3 rows from the database:
<form>
<input id="Amount1" value="<?php echo $databaseValue; ?>" >
<input id="Amount2" value="<?php echo $databaseValue; ?>" >
<input id="Amount3" value="<?php echo $databaseValue; ?>" >
<input type="hidden" name="numberOfRows">
<input id="finalResult">
</form>
This is all done with the mysqli_array function. The value of numberOfRows is based on numRows function.
What I'd like to achieve is that javascript calculates the value of each existing input and put the result in finalResult, regardless the number of forms (because this may vary). If I make some changes to one of the values, the finalResult should update real-time.
What I've tried so far:
formnum contains the number of fields.
var a is created at the beginning, starting at 0. Inside it's function I create an ID, matching the fields on the page. All fields are named "Amount" + number. If this number equals the number of fields, the function will stop. This way the script won't be looking for fields that doesn't excist.
Then it gets the value of this field and adds the value to var b. var b is just created to store the value temporary, untill the function's over.
At the end the total is divided to 15. This is something extra I need. Nothing special on this line.
My code:
<script type='text/javascript'>
$(document).ready(function(){
var formnum = $("#numberOfRows").val();
var a;
var b = 0;
var formname = '#Amount';
for (a = 0; a < formnum; a++) {
var complete = formname.concat(a);
var completeContent = $(complete).val();
b = b + completeContent;
};
b = b.toFixed(2);
});
$(document).mousemove(function(event){
var formula_finalResult = b / 15;
var total_finalResult = Math.floor(formula_finalResult);
$("#finalResult").val(total_finalResult);
});
</script>
This doesn't do anything. It doesn't change the value. What's going wrong?
Make it simple:
$(function(){
var sum = 0;
// Selector to select all input whose id starts with Amount
$("input[id*='Amount']").each(function(){
sum += +$(this).val(); // Parsing as int and adding it to sum
});
$("#finalResult").val(Math.floor(sum/15)); // Storing the values
})
Assuming that all of the fields always have Amount at the beginning of their id attribute, you could use jQuery's ID selector to achieve this, without the need for any of the internal counters, etc.
I'm not entirely sure why you need to hook into the mousemove event, since the data should never change on the page (since it's being generated by PHP when the page is first loaded). The following code should achieve what you're looking for:
$(function() {
var total = 0;
$('input[id*="Amount"]').each(function() { total+= parseFloat( $(this).val() ); });
$('#finalResult').val( Math.floor( total / 15 ) );
});
Your code has an error Uncaught ReferenceError: b is not defined
see it in action here: http://jsfiddle.net/ca9vascj/
There's no reason to bring the mousemove event into this, I'm not even sure what that was needed for.
Like the above answers, here's a much simplified version. But instead of a partial ID selection, let's just give the form an ID, and then give all the needed elements inside that form a class that we can select by. We also no longer need to have the numberOfRows form element.
<form id="theForm">
<input class="formAmmount" value="5" />
<input class="formAmmount" value="10" />
<input class="formAmmount" value="27.5" />
<input class="formAmmount" value="4" />
<input class="formAmmount" value="9" />
<hr />
<input id="finalResult" />
</form>
And then our jQuery code can be reduced to this:
$(function(){
var total = 0;
$("#theForm .formAmmount").each(function(){
total += parseFloat(this.value, 10);
});
var final = Math.floor(total.toFixed(2) / 15);
$("#finalResult").val(final);
});
See it in action here: http://jsfiddle.net/ca9vascj/1/
You dont'need jQuery. The simplest way to do this is document.getElementsByTagName:
var inputs = document.getElementById('my-form').getElementsByTagName('input')
That's it. inputs.length will always get an actual count of inputs in your form. That's because getElementsByTagName() returns a NodeList object, containing a live view of the matching elements. This object is mutable; it will change in response to DOM mutations.
So if you need to get sum from all of the inputs:
function sum() {
var result = 0;
[].slice.call(inputs).forEach(function(input){
result += parseFloat(input.value)
});
return result;
}
If you are able to change the generated Html-Source I would suggest to give a new class to your InputElements.
<input id="Amount1" class="ElementToCount" value="<?php echo $databaseValue; ?>" >
Then you can calculate like that
var getSumOfElements = function() {
var Elements = $('.ElementToCount')
var sum=0
if (Elements && Elements.length>0) {
for (var i=0; i<Elements.length; i++) {
sum += Elements[i].val();
}
}
return sum
}
And to update the field you could register to the 'change'-Event
$('.ElementToCount).on('change', function() {
$('#finalResult').val(getSumOfElements());
})
I am looking for a way to add the following row of inputs using a button (and I've found plenty of examples) BUT most of them renames the name of html element (e.g. name = 'price1', name = 'price2') but my javascript references the element's id, making it erroneous when new rows are added. Some helps are appreciated.
JS Fiddle just to see the rows
https://jsfiddle.net/n4h5uwvk/
the HTML code
<form action = "" method = "POST">
<label>Item : </label>
<select id = 'item_name' name = 'item_name' onChange = 'listMatch(this);fieldCheck();'
>
<option value = "" disabled = "disabled" selected="selected">Please Select</option>
<?php
while($row = mysqli_fetch_assoc($result)){
echo "<option value = '".$row['PRODUCT_ID']."' data-price ='
".$row['UNIT_PRICE']."' >".$row['PRODUCT_NAME']."</option>";
}
?>
</select>
<label>Price : </label>
<input type = 'text' id = 'item_price' name = 'item_price' value = '' disabled/>
<label>Quantity : </label>
<input type = "number" id = 'quantity' name = 'quantity' max = "150" min = "0" onChange = 'multiplier(value)' disabled/>
<label>Sub-Total : </label>
<input type = "number" id = 'sub-total' name = 'sub-total' disabled value = ''/>
and the Javascript
<script>
//lists the price according to selected item
function listMatch(product){
var x = product.options[product.selectedIndex].getAttribute('data-price');
document.getElementById('item_price').value = x;
}
//un-disable quantity field after item is selected
function fieldCheck(){
document.getElementById('quantity').removeAttribute('disabled');
}
//var z = quantity*price
function multiplier(value){
var x = document.getElementById('item_price').value;
var y = value;
var z = x*y;
document.getElementById('sub-total').value = z.toFixed(2);
}
//clone fields on 'add field' button click
Updated :
I found a code to clone my forms well, but I encounter another problem. The clone will always duplicate values of the first row, I want to create child rows that have empty values. Any ways around this code?
//global variable for duplication identification
var count = 1;
//clone form for multiple entries
(function() {
$('#add').click(function() {
var source = $('form:first'),
clone = source.clone();
clone.find(':input').attr('id', function(i, val) {
return val + count;
});
clone.insertBefore(this);
count++;
});
})();
As you know id has to be unique and adding numbers to the cloned form elements to keep the ids unique seems overdoing it.
Names don't have to be unique though, so you can have different forms with elements with the same name. And they can be accessed easily by their names:
<form name="form_1">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
<form name="form_2">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
You can use the form name to access specific element, to access the input with name="firstName" in form_1 and form_2 you can use:
var firstName1 = document.form_1.firstName;
var firstName2 = document.form_2.firstName;
So it will be easy to distinguish between different forms, although their elements have the same structure and names. You just create a new form with name="form_X" and use innerHTML to add the cloned elements.
And to clone an element you can use .cloneNode(true); (or jQuery's clone()).
EDIT:
You still seem to think of it that you need to store everything in a variable, here's an example to do it all, and you can see it's much simpler than you think. I give these forms class="contactForm" to separate them from other forms there might be. we can clone 10 .contactForm and have 100 other forms in the page as well.
To get number of forms you can use $('form.contactForm').length
To empty text inputs inside new form you can use: newForm.find('input[type=text]').val("");
jsfiddle DEMO