This is my code in html and java script. I coded same things thrice, I want to do it once... what to do...............
<input type="text" name="option1" id="option1" onblur="calc_amt(1);">
<input type="text" name="price1" id="price1" onblur="calc_amt(1);">
<input type="text" name="amount1" id="amount1" readonly>
<input type="text" name="option2" id="option2" onblur="calc_amt(2);">
<input type="text" name="price2" id="price2" onblur="calc_amt(2);">
<input type="text" name="amount2" id="amount2" readonly>
<input type="text" name="option3" id="option3" onblur="calc_amt(3);">
<input type="text" name="price3" id="price3" onblur="calc_amt(3);">
<input type="text" name="amount3" id="amount3" readonly>
<script>
function calc_amt(val){
if(val==1){
var option1 = document.getElementById("option1").value;
var pri1 = document.getElementById("price1").value;
....
document.getElementById("amount1").value=amoun1 ;
}
if(val==2){
var option2 = document.getElementById("option2").value;
var pri2 = document.getElementById("price2").value;
...
document.getElementById("amount2").value=amoun2;
}
if(val==3){
var option3 = document.getElementById("option3").value;
var pri3 = document.getElementById("price3").value;
....
document.getElementById("amount3").value=amoun3;
}
var amoun1=document.getElementById("amount1").value;
var amoun2=document.getElementById("amount2").value;
var amoun3=document.getElementById("amount3").value;
var tot = Number(amt1)+Number(amt2)+Number(amt3);
document.getElementById("amount").value=tot;
}
</script>
how do solve it by coding only once... I am beginner please help me.... any other ideas to solve this.. i need a solution like inheritance.
You can further reduce above script like this. Your amoun is unclear for though. However you can reduce the code like this. This is just an idea and make sure you match the variables with correct statement.
<script>
function calc_amt(val){
var option1 = document.getElementById("option"+val).value;
var pri1 = document.getElementById("price"+val).value;
....
document.getElementById("amount"+val).value=""+amount+val ;
var amoun1=document.getElementById("amount1").value;
var amoun2=document.getElementById("amount2").value;
var amoun3=document.getElementById("amount3").value;
var tot = Number(amt1)+Number(amt2)+Number(amt3);
document.getElementById("amount").value=tot;
}
</script>
Replace:
if(val==1){
var option1 = document.getElementById("option1").value;
var pri1 = document.getElementById("price1").value;
document.getElementById("amount1").value=amoun1 ;
}
with:
var amoun = document.getElementById("amount" + val).value;
var option = document.getElementById("option" + val).value;
var pri = document.getElementById("price" + val).value;
document.getElementById("amount" + val).value=amoun;
TRY...
Remove all inline handler and use blur handler like in demo
$("input[type=text]").on("blur", function () {
var id = this.id;
var last = id.charAt(id.length - 1); // get last id string value
var optionValue = $("#option" + last).val();
var priceValue = $("#price" + last).val();
var option = isNaN(optionValue) ? 0 : +optionValue; // check is nan
var price = isNaN(priceValue) ? 0 : +priceValue;
$("#amount" + last).val(option * price); // display multiply value
$("#amount").text($("input[type=text][id^=amount]").map(function () { // collect all amount1,2,3 values
var value = $(this).val();
return isNaN(value) ? 0 : +value;
}).get().reduce(function (a, b) { // add total value
return a + b;
}));
});
DEMO
OPTIMIZED CODE
$("input[type=text]:not([readonly])").on("blur", function () {
var obj = $();
obj = obj.add($(this)).add($(this).prevUntil('[readonly]')).add($(this).nextUntil('[readonly]'));
$(this).nextAll('[readonly]').first().val($.map(obj, function (val, i) {
return parseInt(val.value, 10) || 0;
}).reduce(function (a, b) {
return a * b
}, 1));
$("#amount").text($("input[type=text][id^=amount]").map(function () {
var value = $(this).val();
return isNaN(value) ? 0 : +value;
}).get().reduce(function (a, b) {
return a + b;
}));
});
DEMO
Related
I'm trying to obtain a value out of an HTML slider so I can dynamically use it as an integer in JavaScript.The problem I'm having is I can't seem to use the value as a proper integer.
For example, if my slider value was 5 & if l tried to store it in a variable and add 10, it would output as '510' instead.
Maybe I'm an idiot and missing something very fundamental or simple, but it always ends up as a string in the end.I have tried parseInt() as well, but it doesn't seem to help.
I've set up a simple example of code below:
JS
var sliderUnit = document.getElementById("slider");
var outputUnit = document.getElementById("amtOutput");
var a = 0;
var b = 10;
outputUnit.innerHTML = sliderUnit.value;
sliderUnit.oninput = function(){
outputUnit.innerHTML = this.value;
console.log(sliderUnit.value);
a = this.value;
parseInt(a);
}
function test(){
b += a;
console.log("b: " + b + " | a: " + a);
}
HTML
<div class="sliderContainer">
<input type="range" min="1" max="15" value="7" id="slider">
<input type="submit" value="Submit" onclick="test()" />
| Slider number: <span id="amtOutput"></span>
</div>
The problem is that your are calling the parseInt(a) but the returned Integer value is not being handled properly, you should do as this a = parseInt(a);
var sliderUnit = document.getElementById("slider");
var outputUnit = document.getElementById("amtOutput");
var a = 0;
var b = 10;
outputUnit.innerHTML = sliderUnit.value;
sliderUnit.oninput = function(){
outputUnit.innerHTML = this.value;
console.log(sliderUnit.value);
a = this.value;
a = parseInt(a); // Change this line
}
function test(){
b += a;
console.log("b: " + b + " | a: " + a);
}
<div class="sliderContainer">
<input type="range" min="1" max="15" value="7" id="slider">
<input type="submit" value="Submit" onclick="test()" />
| Slider number: <span id="amtOutput"></span>
</div>
If not the variable a will continue to be a string becouse it wasn't changed
You need to parse the string as int using parseInt.
Working code:
var sliderUnit = document.getElementById("slider");
var outputUnit = document.getElementById("amtOutput");
var a = 0;
var b = 10;
outputUnit.innerHTML = sliderUnit.value;
sliderUnit.oninput = function(){
outputUnit.innerHTML = this.value;
console.log(sliderUnit.value);
a = this.value;
parseInt(a);
}
function test(){
b = parseInt(b)
a = parseInt(a);
b += a;
console.log("b: " + b + " | a: " + a);
}
<div class="sliderContainer">
<input type="range" min="1" max="15" value="7" id="slider">
<input type="submit" value="Submit" onclick="test()" />
| Slider number: <span id="amtOutput"></span>
</div>
Working JSFiddle
(ETA: I'm working on this for a class and the teacher wants everything to be "oninput"...yes, it's annoying :p )
I'm working on a form where each function miltiplies a number and gives me a "subtotal" on input. I'd like to take the two "subtotal" answers from the two functions and add them togething into a "total" amount. I feel like this should be simple but nothing I've tried works.
Here's what I've got in the javascript that works to give me the two subtotals:
function myCalculator() {
var qty1 = document.getElementById('qty1').value;
document.getElementById('subTotalOne').innerHTML = '$ ' + qty1 * 19.99;
}
function myCalculatorTwo() {
var qty2 = document.getElementById('qty2').value;
document.getElementById('subTotalTwo').innerHTML = '$ ' + qty2 * 37.99;
}
Here's the important parts of the html:
<div class="qty">
<label for="qty">Qty</label><br>
<input type="number" id="qty1" placeholder="0" oninput="myCalculator()"/><br>
<input type="number" id="qty2" placeholder="0" oninput="myCalculatorTwo()"/><br>
</div>
<div class="price">
<label for="price">Price</label>
<p>$19.99</p>
<p>$37.99</p>
</div>
<div class="subtotal">
<label for="subTotal">Total</label><br>
<span class="subTotalOne" id="subTotalOne">$</span><br>
<span class="subTotalTwo" id="subTotalTwo">$</span><br>
</div>
<div class="total">
<label for="total">Order Total</label><br>
<span class="orderTotal" id="orderTotal" oninput="orderTotal()">$</span><br>
</div>
I'm trying to add the subTotalOne and subTotalTwo and have them output at orderTotal, essentially. :)
Thanks!
//Global variables (concidering ID is unique)
let subTotalOne, subTotalTwo, qty1, qty2, orderTotal;
const setup = () => {
subTotalOne = document.getElementById('subTotalOne');
subTotalTwo = document.getElementById('subTotalTwo');
qty1 = document.getElementById('qty1');
qty2 = document.getElementById('qty2');
orderTotal = document.getElementById('orderTotal');
myCalculator();
myCalculatorTwo();
};
const updateTotal = (target, value) => {
if(target == null || value == null || Number.isNaN(value)) return;
target.textContent = `$ ${value.toFixed(2)}`;
target.setAttribute('data-value', value.toFixed(2));
}
const getTotal = () => {
if(subTotalOne == null || subTotalTwo == null) return 0;
const [value1, value2] = [
Number.parseFloat((subTotalOne.dataset?.value ?? 0), 10),
Number.parseFloat((subTotalTwo.dataset?.value ?? 0), 10)
];
if(Number.isNaN(value1) || Number.isNaN(value2)) return;
else return value1 + value2;
};
const updateOrderTotal = () => updateTotal(orderTotal, getTotal());
const myCalculator = () => {
const value = Number.parseFloat(qty1.value || 0, 10) * 19.99;
updateTotal(subTotalOne, value);
updateOrderTotal();
}
const myCalculatorTwo = () => {
const value = Number.parseFloat(qty2.value || 0, 10) * 37.99;
updateTotal(subTotalTwo, value);
updateOrderTotal();
}
window.addEventListener('load', setup);
<div class="qty">
<label for="qty">Qty</label><br>
<input type="number" id="qty1" placeholder="0" oninput="myCalculator()" min="0"><br>
<input type="number" id="qty2" placeholder="0" oninput="myCalculatorTwo()" min="0"><br>
</div>
<div class="price">
<label for="price">Price</label>
<p data-value="19.99">$19.99</p>
<p data-value="37.99">$37.99</p>
</div>
<div class="subtotal">
<label for="subTotal">Total</label><br>
<span class="subTotalOne" id="subTotalOne">$</span><br>
<span class="subTotalTwo" id="subTotalTwo">$</span><br>
</div>
<div class="total">
<label for="total">Order Total</label><br>
<span class="orderTotal" id="orderTotal" oninput="orderTotal()">$</span><br>
</div>
Here's how you do it:
function orderTotal() {
const qty1 = document.getElementById('qty1').value;
const qty2 = document.getElementById('qty2').value;
const total = parseInt(qty1) + parseInt(qty2);
document.getElementById('orderTotal').innerHTML = '$ ' + total;
}
Remove the oninput="orderTotal()" in your span element and trigger the above function using a button click e.g. <button onClick="orderTotal()">Calculate Total</button> or maybe when either of your two inputs' value changes. Also consider using const and let instead of var.
https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/
Instead of querying the DOM in Ray's answer--as DOM queries should generally be avoided since they are slow W3 Wiki, you could also consider using a shared variable between the two functions.
Also, consider using something else in place of innerHTML, mostly because of efficiency why-is-element-innerhtml-bad-code.
var total1;
var total2;
function myCalculator() {
var qty1 = document.getElementById('qty1').value;
total1 = qty1 * 19.99
document.getElementById('subTotalOne').textContent = '$ ' + total1;
}
function myCalculatorTwo() {
var qty2 = document.getElementById('qty2').value;
total2 = qty2 * 37.99;
document.getElementById('subTotalTwo').textContent = '$ ' + total2;
}
function orderTotal() {
document.getElementById('orderTotal').innerHTML = '$ ' + (total1 + total2);
//parentheses because '$' isn't a number so the numbers total1 and total2 will be treated like strings and joined together
}
I try to create array with keys and values by using the jQuery .map().
When I use my code I have a problem with formatting:
["name1:1", "name2:1", "name3:0"]
I need:
['name1':1,'name2':1,'name3':0]
I spend a few hours to make it work, but I don't know what is wrong.
HTML
<div class="inputs-container">
<input id="name1" name="name1" type="checkbox" class="multicheckbox-item" value="1" checked="checked">
<input id="name2" name="name2" type="checkbox" class="multicheckbox-item" value="1" checked="checked">
<input id="name3" name="name3" type="checkbox" class="multicheckbox-item" value="0">
</div>
JS
var inputsContainer = $('.inputs-container');
var inputValues = inputsContainer.find( 'input.multicheckbox-item' ).map( function() {
var name = $(this).attr('name');
var active = 0;
if( $(this).prop( 'checked' ) ){
var active = 1;
}
return name + ':' + active;
}).get();
console.log( inputValues );
You'll want an object and .each (or .forEach in native array terms).
var inputsContainer = $('.inputs-container');
var inputValues = {};
var inputValues = inputsContainer.find('input.multicheckbox-item').each( function() {
inputValues[$(this).attr('name')] = ($(this).prop('checked') ? 1 : 0);
});
console.log(inputValues);
Try This
var inputsContainer = $('.inputs-container');
var inputValues_key = inputsContainer.find( 'input.multicheckbox-item' ).map(function() {
var name = $(this).attr('name');
return name;
}).get();
var inputValues_value = inputsContainer.find( 'input.multicheckbox-item' ).map(function() {
var active = $(this).prop('checked')? 1 : 0;
return active;
}).get();
var inputValues = [], length = Math.min(inputValues_key.length, inputValues_value.length);
for(var i = 0; i < length; i++) {
inputValues.push([inputValues_key[i], inputValues_value[i]]);
}
console.log( inputValues );
Updated after the hint in comments.
Current jsfiddle
Is there a way so that I only have to write the script once and use it for multiple ID's?
I currently have 3 checkboxes so I just copied the code 3 times but if I get for example a 100 checkboxes I can't imagine copying this a 100 times would be verry effecient
Current code
Javascript
var elem1 = document.getElementById('div_product_1'),
checkBox1 = document.getElementById('product_1');
checkBox1.checked = false;
checkBox1.onchange = function () {
elem1.style.display = this.checked ? 'block' : 'none';
};
checkBox1.onchange();
var elem2 = document.getElementById('div_product_2'),
checkBox2 = document.getElementById('product_2');
checkBox2.checked = false;
checkBox2.onchange = function () {
elem2.style.display = this.checked ? 'block' : 'none';
};
checkBox2.onchange();
var elem3 = document.getElementById('div_product_3'),
checkBox3 = document.getElementById('product_3');
checkBox3.checked = false;
checkBox3.onchange = function () {
elem3.style.display = this.checked ? 'block' : 'none';
};
checkBox3.onchange();
HTML
<input type="checkbox" name="product_1" id="product_1" />
<label>Product 1</label><br>
<div id="div_product_1">
<input type="number" name="quantity_1" id="quantity_1" />
</div>
<input type="checkbox" name="product_2" id="product_2" />
<label>Product 2</label><br>
<div id="div_product_2">
<input type="number" name="quantity_2" id="quantity_2" />
</div>
<input type="checkbox" name="product_3" id="product_3" />
<label>Product 3</label><br>
<div id="div_product_3">
<input type="number" name="quantity_3" id="quantity_3" />
</div>
As alluded to in the comments, you are reusing your elem variable. Change your code so the second and third elem are unique, i.e. this jsfiddle
You can maybe try something like this. Fiddle
This is mostly so that you don't have to copy paste the whole time.
So in a nutshell, i am adding the html controls dynamically and then hooking up the onchange event on the checkboxes
HTML
<div id="placeholder"></div>
JS
var max_fields = 100; //maximum input boxes allowed
var $placeholder = $("#placeholder");
// Add html controls
for (var i = 0; i < max_fields; i++) {
$placeholder.append("<input type='checkbox' name='product_" + i + "' id='product_" + i + "'/>")
.append("<label>Product " + i + "</label")
.append("<div id='div_product_" + i + "'></div>");
var $divProduct = $("#div_product_" + i);
$divProduct.append("<input type='number' name='quantity_" + i + "' id='quantity_" + i + "' class='hide' />");
}
// wire the onclick events
$('[id*="product_"]').change(function () {
console.log($(this));
var splitId = $(this).attr("id").split("_")[1]
console.log({
id: splitId,
control: $("#quantity_" + splitId)
})
$("#quantity_" + splitId).toggle()
});
IMHO, loops should do. Also, use class instead of id on your HTML elements.
Snippet:
var numProducts=10;
var classNameProduct='product';
var classNameContainerProduct='div_product';
var classNameQuantity='quantity';
var mainContainer=document.body;
function generateMarkup(){
for(var i=0; i<numProducts; i+=1){
mainContainer.insertAdjacentHTML('beforeend','<input type="checkbox" name="'+classNameProduct+'" class="'+classNameProduct+'"/><label>Product '+i+'</label><br>');
mainContainer.insertAdjacentHTML('beforeend','<div class="'+classNameContainerProduct+'"><input type="number" name="'+classNameQuantity+'" class="'+classNameQuantity+'"/></div>');
}
}
function initCheckboxes(){
var checkboxes=document.querySelectorAll('.'+classNameProduct),containerProducts=document.querySelectorAll('.'+classNameContainerProduct);
for(var i=0; i<numProducts; i+=1){
checkboxes[i].checked=false;
containerProducts[i].style.display='none';
(function(index){
checkboxes[index].onchange=function(){ containerProducts[index].style.display=this.checked?'block':'none'; }
}(i));
}
}
generateMarkup();
initCheckboxes();
Hope this helps.
I have a textbox where the user can input a value into a listbox. Then, I have buttons to either Delete that value, or Sort the value.
My problem is that I want the value to be sorted by those 2 separated values. For example, the user would enter City=Chicago in the textbox. And there would be 2 sort buttons, to 'Sort by City' and 'Sort by Value' where value in this case is Chicago.
So after hours of trying I can't figure out how to:
1. Restrict the user to only be able to enter a value like %=% (e.g. City=Chicago)
2. Have separate sort buttons for the values on either side of the equal sign
http://jsfiddle.net/uudff585/6/
<div class='teststyles'>
<h3>Test</h3>
Name/Value Pair
<br />
<input id="PairTextbox" type="text" value="city" />=<input id="PairTextbox1" type="text" />
<input type="button" value="Add" id="addButton" />
<br />
<br />Name/Value Pair List
<br />
<select multiple="multiple" id="PairListbox"></select>
<input type="button" value="Sort By Name" sort-type="0" id="sortName">
<input type="button" value="Sort By Value" sort-type="1" id="sortValue"><br>
<input type="button" value="Delete" id="deleteButton" />
Script:
var listArray = [];
function addNewItem() {
console.log("ok2");
var textbox = document.getElementById('PairTextbox');
var textbox1 = document.getElementById('PairTextbox1');
var listbox = document.getElementById('PairListbox');
var newOption = document.createElement('option');
newOption.value = listArray.length-1; // The value that this option will have
newOption.innerHTML = textbox.value + "=" + textbox1.value; // The displayed text inside of the <option> tags
listbox.appendChild(newOption);
listArray.push([textbox.value, textbox1.value, ]);
}
function deleteItem() {
var listbox = document.getElementById('PairListbox');
if (listbox.selectedIndex != -1) {
console.log(listbox.selectedIndex);
delete listArray[listbox.value];
listbox.remove(listbox.selectedIndex);
}
}
function sortItems(e) {
var sorttype = e.target.getAttribute("sort-type");
var $listbox = document.getElementById('PairListbox');
var $options = listArray.map(function (option) {
return option;
});;
$options.sort(function (a, b) {
var an = a[sorttype],
bn = b[sorttype];
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
$listbox.innerHTML = "";
$options.forEach(function ($option, index) {
var newOption = document.createElement('option');
newOption.value = index; // The value that this option will have
newOption.innerHTML = $option[0] + "=" + $option[1]; // The displayed text inside of the
$listbox.appendChild(newOption);
});
}
document.getElementById('addButton').addEventListener('click', addNewItem);
document.getElementById('sortName').addEventListener('click', sortItems);
document.getElementById('sortValue').addEventListener('click', sortItems);
document.getElementById('deleteButton').addEventListener('click', deleteItem);
For those who would like to use jQuery, validation and auto-sorting this FIDDLE. The HTML is:
<div class='teststyles'>
<h3>Test</h3>
<p>Name/Value Pair</p>
<p><input id="PairTextbox" type="text" /> <input type="button" value="Add" id="addButton" /></p>
<p>Name/Value Pair List</p>
<p><select multiple="multiple" id="PairListbox"></select></p>
<p>
<input id="byname" type="radio" name="sortby" value="name" checked="checked" /> <label for="byname">sort by name</label><br />
<input id="byvalue" type="radio" name="sortby" value="value" /> <label for="byvalue">sort by value</label>
</p>
<p><input type="button" value="Delete selected" id="deleteButton" /></p>
</div>
and the script:
// Keep your pairs in memory
var pairs = [];
// Keep record of dynamic elements
var listbox = $('#PairListbox');
var textbox = $('#PairTextbox');
var sortInput = $('input[name=sortby]');
function sortItems() {
sortType = sortInput.filter(':checked').val();
if ( sortType=='name' ) {
// Sort by key
console.log( 'sort by key' );
pairs = pairs.sort(function (a, b) {
return a.k.localeCompare(b.k);
});
} else {
// Sort by value
console.log( 'sort by val' );
pairs = pairs.sort(function (a, b) {
return a.v.localeCompare(b.v);
});
};
console.log( pairs );
console.log( '----------' );
};
function printItems() {
var optionsHtml = '';
$.each(pairs, function(i, item) {
optionsHtml += '<option value="' + item.k + '=' + item.v + '">' + item.k + '=' + item.v + '</option>';
});
listbox.html(optionsHtml);
};
// Customize validation of new input
function validateInput() {
var str = textbox.val().replace(/\s+/g, '_');
var splited = str.split('=');
if (splited.length == 2 && splited[0] && splited[1]) {
// Maybe also check if pair already exists in array?
pairs.push({
k: splited[0],
v: splited[1]
});
return true;
} else {
false;
};
}
function addNewItem() {
if (validateInput()) {
sortItems();
printItems();
} else {
alert('Wrong input value!');
}
}
function deleteItem() {
var selectedItems = listbox.find('option:selected');
selectedItems.each(function(i) {
var thisItem = $(this);
var thisValueSplit = thisItem.val().split('=');
pairs = pairs.filter(function (el) {
return !(el.k==thisValueSplit[0] && el.v==thisValueSplit[1]);
});
printItems();
});
}
$('#addButton').on('click', addNewItem);
$('#deleteButton').on('click', deleteItem);
sortInput.on('change', function(e) {
sortItems();
printItems();
});