Checkbox not working on checked to add values - javascript

I have created calculation system project with javascripts all things are good calculation done perfectly tax include perfectly but tax not included when I click on checkebox, it add when I type something in input field, I want values changes on when I clicked on checkbox and even when I type something
html
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1"></span>
</div>
javascript
$('input').keyup(function(){ // run anytime the value changes
var BMS_qty = Number($('#BMS_qty').val());
var BMS_price = Number($('#BMS_price').val());
if(document.getElementById("tax").checked) {
var tax = 0.17;
} else {
tax = 0;
}
var subtotal = BMS_qty * BMS_price;
var total = tax * subtotal;
$('#total_expenses1').html(total + subtotal); // add them and output it
// add them and output it
});

The problem is that the keyup() method will only act on an <input type="checkbox"> when the space key is pressed to activate it.
To avoid this kind of problem I'd suggest switching the code to react to input events (which covers any event in which the value/state of an <input> is changed).
One approach to solving the problem is below, with explanatory comments included:
// we select all <input> elements regardless of their type attribute,
// and bind the anonymous function of the on() method as the event-handler
// for the 'input' event:
$('input').on('input', function() {
// switching to the use of const to declare variables that shouldn't
// change after they've been defined, and we use parseInt() instead
// of Number() to convert those the entered-values into numbers
// supplying the radix (base) argument of 10 because we're working
// with base-10 numbers (this is largely a personal preference, I
// don't think there's a particular argument for, or against, this
// change):
const BMS_qty = parseInt($('#BMS_qty').val(), 10),
BMS_price = parseFloat($('#BMS_price').val()),
// here we use a conditional (ternary) operator, in which we
// assess - using the .is() method - whether the element with
// the id of "tax" is checked.
// If it is checked the value of tax is 0.17, if it is not
// the value is 0:
tax = $('#tax').is(':checked') ? 0.17 : 0;
// using let to declare variables that may need to change if
// the calculations/results need to be modified in production:
let subtotal = BMS_qty * BMS_price,
total = tax * subtotal;
// adding the values, andd writing it the element with an
// id equal to "total_expenses", though I've switched to using
// the text() method to avoid accidentally trying to insert any
// HTML elements in the future:
$('#total_expenses1').text(total + subtotal);
});
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1"></span>
</div>
JS Fiddle demo.
References:
JavaScript:
Conditional ("ternary") Operator.
parseFloat().
parseInt().
jQuery:
is().
on().
text().

You need to use on() to get events you need
I think, you also need to change Number() by parseInt()
$(document).on('keyup keypress keydown change', 'input[name="BMS_qty"], input[name="BMS_price"], input[name="taxamount"]', function(){ // or keypress I have the same result
var BMS_qty = parseInt($('#BMS_qty').val());
var BMS_price = parseInt($('#BMS_price').val());
if(document.getElementById("tax").checked) {
var tax = 0.17;
} else {
tax = 0;
}
var subtotal = BMS_qty * BMS_price;
var total = tax * subtotal;
$('#total_expenses1').html(total + subtotal); // add them and output it
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group row">
<div class="col-sm-6">
<input type="float" class="form-control form-control-user" id="BMS_qty" name="BMS_qty" placeholder="BMS Quantity">
<input type="float" class="form-control form-control-user" id="BMS_price" name="BMS_price" placeholder="BMS Price">
</div>
</div>
<div class="col-sm-6 form-check">
<input type="checkbox" id="tax" name="taxamount" value="0.17">
<label for="tax">Included Tax</label><br>
<label for="total_expenses1" style="text-align: right;">Total:- </label>
<span id="total_expenses1">0</span>
</div>

Related

How to Remove a Div using variable parameters?

I'm trying to create a way to add entries to my form so that the user can choose how many he wants, but I can't get the remove part working.
JavaScript
var i = 1;
var divContent = document.getElementById('formulario');
//Click to add a field
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}
function remove(div1, div2){
var div = document.getElementById(div1);
var div2 = document.getElementById(div2);
div.remove();
div2.remove();
i--;
}
And now the HTML
<form>
<h4 class="card-tittle text-center">Taxas</h4>
<div id="formulario" class="form row align-items-start">
<div class="mb-1 col-3" id="0">
<label for="nomeTx0" class="form-label">Nome</label>
<input type="text" class="form-control" id="nomeTx0" name="nomeTx0" required>
</div>
<div class="mb-1 col-3" id="0">
<label for="taxa0" class="form-label">Valor</label>
<input type="float" class="form-control" id="taxa0" name="taxa0" required>
</div>
</div>
+ adicionar campo
<div class="mb-1 col-lg-12" style="text-align: center;">
<button class="btn btn-primary col-5" id="Enviar" type="submit" text="Enviar">Adicionar Taxas</button>
</div>
</form>
ID="taxa"+i but when I call the remove(); error is printed to me saing the variable is null.
This is really not the right approach in the first place.
Your fundamental problem is that you are relying on ids to know what element(s) to add and remove and this is leading you to concatenate an id onto dynamically created elements, made from long strings with variables concatenated into them. In reality, you should avoid ids whenever possible as they make your code very brittle and don't scale well.
This is a perfect use for the HTML <template> element. As you can see from the re-worked code below, all ids have been removed - - you don't need them. Additionally, instead of long strings with a variable concatenated into it, you just need to copy/clone the template whenever you need one. Then, you can use "event delegation" and smartly organized HTML to just set up a single click event on a master wrapper element, where the actual element that was clicked (the event.target) can be checked. If it was a remove button, then just remove the entire wrapper that is the nearest ancestor to the remove button that was clicked.
You can now add and remove as many items as you like with no need for an id or counting variables!
// Get a reference to the template, outer div and the add "button"
const template = document.querySelector("template");
const wrapper = document.querySelector(".wrapper");
const add = document.querySelector(".add");
// Set up the add event in Javascript, not with inline HTML
add.addEventListener("click", function(event){
var clone = template.content.cloneNode(true); // Clone the template
wrapper.appendChild(clone);
});
// Set up a wrapper level click event that any clicks within it will bubble up to
wrapper.addEventListener("click", function(event){
// Test to see if it was remove "button" that was clicked
if(event.target.classList.contains("remove")){
// Just remove the closest ancestor div that holds that particular group
// and remove it.
event.target.closest("div.templateWrapper").remove();
}
});
.mb-1.col-lg-12 {
text-align:center;
}
.mb-1.col-3 {
margin:2px;
}
.add, .remove {
cursor:pointer;
color:blue;
}
.labelName { display:inline-block; width:3em; }
/* This is just to better see the groups */
.templateWrapper, .form {
background-color:aliceblue;
padding:5px;
margin:8px;
}
<!-- This will not initially be shown on the page.
It will be used to copy from when/if needed. -->
<template>
<div class="templateWrapper">
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Nome</span>
<input type="text" class="form-control" name="nomeTx" required>
</label>
</div>
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Valor</span>
<!-- An input does not have a type=float -->
<input class="form-control" name="taxa" required>
</label>
</div>
<span class="remove">- Remover campo</span>
</div>
</template>
<form>
<h4 class="card-tittle text-center">Taxas</h4>
<!-- Hyperlinks are for navigation, not JavaScript click hooks. Any visible element
supports a click event. Use span and div for generic clickable inline or block
elements that need to have click event handlers. -->
<span class="add">+ adicionar campo</span>
<div class="wrapper">
<div class="form row align-items-start">
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Nome</span>
<input type="text" class="form-control" name="nomeTx0" required>
</label>
</div>
<div class="mb-1 col-3">
<label class="form-label"><span class="labelName">Valor</span>
<input type="float" class="form-control" name="taxa0" required>
</label>
</div>
</div>
</div>
<div class="mb-1 col-lg-12">
<!-- A button does not have a "text" attribute -->
<button class="btn btn-primary col-5" type="submit">Adicionar Taxas</button>
</div>
</form>
You would like to pass the ids of the html elements to function remove , instead you pass something else.
Try this:
function remove(d1, d2){
//what are passing to function... id , or something else ?
console.log(d1,d2);
// now I force the arguments passed to function to a valid value id for test
var a = document.getElementById('div1'); // id is div1
var b = document.getElementById('div21'); // id is div21
//Ask to parentNode to remove his child
a.parentNode.removeChild(a);
b.parentNode.removeChild(b);
i--;
}
The problem in your code is that you don't pass a string to the remove function but instead you pass the whole element. That is why document.getElementById can't find anything because it expects a string as a parameter. I refactored you code a bit and also when removing the fields the link - Remover campo stayed and was not deleted. I fixed that as well by passing a third argument to the remove function.
var i = 1;
var divContent = document.getElementById('formulario');
//Click to add a field
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}
function remove(div1, div2, link){
var div = document.getElementById(div1);
var div2 = document.getElementById(div2);
var link = document.getElementById(link);
divContent.removeChild(div);
divContent.removeChild(div2);
divContent.removeChild(link)
i--;
}
The easiest way to do your code working it change your function "cria". (it's not the best option)
You miss ' '.
You have this.
onclick="remove(div'+i+',div2'+i+')"
You need this.
onclick="remove(\'div'+i+'\',\'div2'+i+'\')"
Javascript just doesn't understand that these parameters are strings.
And the full function "cria" after changes.
function cria() {
//This add a HTML Inputs and divs who the ID is variable how the 'i' is increasedf
document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div>- Remover campo';
i++;
}

Is there a way that i can connect inputs together?

I have 3 input fields that I would like to connect/link to each other. I want them to have a total value limited to 100%. So if 1 input is 40% then the other 2 input have 60% left to distribute in their value.
I am trying to find my answer on google, but i think I am searching with the wrong criteria. Does somebody know how to do this or have a guide on how to do it?
<div class="form_groep">
<label class="input_label_koolhydraten"><b>Koolhydraten</b></label>
<input class="input_macro_koolhydraten" type="number" name="message" id="macro_koolhyrdaten" required><span>%</span>
</div>
<div class="form_groep">
<label class="input_label_eiwitten"><b>Eiwitten</b></label>
<input class="input_macro_eiwitten" type="number" name="message" id="macro_eiwitten" required><span>%</span>
</div>
<div class="form_groep">
<label class="input_label_vetten"><b>Vetten</b></label>
<input class="input_macro_vetten" type="number" name="message" id="macro_vetten" required><span>%</span><br><br>
</div>
If I understood correctly, you want to have 3 inputs that the sum of its values do not exceeds 100, right?
If yes, so my code below can help you. There you will get all inputs in an array, then add a listener to the change of each one. This Listener will get the value of the input that is being changed and check if its value summed with the value of ther others don't exceed 100.
Check the code and if you didn't understand something, tell in the comments.
Also, warn me if I understood you wrong.
let total = 0;
const ipts = Array.from(document.getElementsByTagName('input'));
const totalElem = document.getElementById("total")
for (var i = 0; i < ipts.length; i++){
ipts[i].onchange = countTotal
}
function countTotal(){
let value = parseFloat(this.value);
total = ipts.reduce((counter,elem) => parseFloat(elem.value) + counter, 0);
total -= value;
if (value > 100){
this.value = 100;
}
if (value + total > 100){
this.value = 100 - total;
}
totalElem.innerText = total + parseFloat(this.value);
}
<div class="form_groep">
<label class="input_label_koolhydraten"><b>Koolhydraten</b></label>
<input class="input_macro_koolhydraten" type="number" name="message" id="macro_koolhyrdaten" required value='0'><span>%</span>
</div>
<div class="form_groep">
<label class="input_label_eiwitten"><b>Eiwitten</b></label>
<input class="input_macro_eiwitten" type="number" name="message" id="macro_eiwitten" required value='0'><span>%</span>
</div>
<div class="form_groep">
<label class="input_label_vetten"><b>Vetten</b></label>
<input class="input_macro_vetten" type="number" name="message" id="macro_vetten" required value='0'><span>%</span><br><br>
</div>
<div><span id="total">0</span> out of 100% </div>
You could listen to change or input events from all of those inputs in js, and then get values from all, count their lengths and if sum_of_their_lengths > some_maximum_value then block them.

Quote Calculator: Finding the sum of 3 previous calculations returns NaN

I've been working on a calculator in Jquery. It's composed of a few initial calcultions that display totals in the frontend.
It calculates the measurements the user inputs and multiplies this with the base product(woocommerce) price to give an initial total.
It allows users to select various addons such as 'cut outs' and calculates the quantity to come up with a total value for the 'add ons'.
It allows users to select a few extras such as 'delivery' via input checkboxes which once again calculates them to provide a total cost for the extra touches.
This leaves me with 3 total figures for the calculator so far in their own fields/divs. I've given these each a class of 'sumthree'.
I'm then wanting to add these totals up to make an overall total for the calculator.
I've tried variations such as trying to pull the data using text, value and HTML. They're not all inputs so value didn't seem correct to me. Ive also tried using parseFloat instead of parseInt but no luck so far.
It always pulls NaN, but from what I can tell I correctly declared 'finalquote' in the code at the end. I'm under the understanding this could've been the issue.
<div class="form-section quote">
<input id="works-result" value="12" readonly>
</div>
<div class="splashback-calc">
<h4>Splashback/s</h4>
<div class="splashback-row">
<div class="form-section form-half-section quote">
<span class="quote-label">Width</span>
<span class="input-wrap currency"><input id="splash-width" type="number" value="0"></span></div>
<div class="form-section form-half-section quote">
<span class="quote-label">Length </span>
<span class="input-wrap currency"><input id="splash-length" type="number" value="0"></span>
</div>
</div>
<div class="additional-splashback"></div>
<a class="clonebutton" href="" >Add More</a>
<div class="form-section quote">
<input id="splash-result" value="0" readonly>
</div>
</div>
<div class="worktop-calc">
<span class="quote-label">Integrity Sink</span>
<div class="input-wrap currency extraproduct" data-price="600.00">
<input type="number" class="extraQuantity" value="0" min="0" max="20" />
<span class="productTotal"></span>
</div>
<span class="quote-label">Pop Up Socket Cut Out</span>
<div class="input-wrap currency extraproduct" data-price="50.00">
<input type="number" class="extraQuantity" value="0" min="0" max="20" />
<span class="productTotal"></span>
</div>
/** 1ST Total I'm Trying to Add **/
<div id="total" readonly="readonly">Total: £<span id="sum" class="sumthree">0.00</span> </div>
</div>
<div class="fitting-calc">
<div class="form-section quote">
<span class="quote-label">Templating</span>
<span class="input-wrap checkbox-wrap"><input type="checkbox" value="120.00"></span>
<br>
<span class="quote-label">Delivery</span>
<span class="input-wrap checkbox-wrap"><input type="checkbox" value="250.00"></span>
</div>
/** 2nd Total I'm trying to add **/
<input id="fittingprice" class="sumthree" type="text" readonly="readonly"/>
</div>
/** 3rd Total I'm trying to add, grabs product price and measurements to calculate the sum **/
<span class="input-wrap total-cost">£<input id="total-cost" class="sumthree" readonly type="number" min="0" step="0.01" data-number-to-fixed="2" data-number-stepfactor="100"></span>
/** The Total of the 3 other Totals I'm trying to solve **/
<span class="input-wrap">£<input id="quotefinal" readonly type="number" min="0" step="0.01" data-number-to-fixed="2" data-number-stepfactor="100"></span>
(function($){
$('.worktop-calc input').change(function() {
var area = $('#works-width').val() * $('#works-length').val()
$('#works-result').val(area)
})
$('.splashback-calc input').change(function() {
var area = $('#splash-width').val() * $('#splash-length').val()
$('#splash-result').val(area)
})
$('.clonebutton').first().click(function(event) {
event.preventDefault();
$( ".splashback-row" ).clone().appendTo( ".splashback-row" );
});
$( '.variations_form' ).each( function() {
jQuery(this).on( 'found_variation', function( event, variation ) {
console.log(variation);//all details here
var price = variation.display_price;//selectedprice
console.log(price);
var totalcost = (price) * $('#works-result').val()
$('#total-cost').val(totalcost)
});
var updateTotal = function() {
var sumtotal;
var sum = 0;
//Add each product price to total
$(".extraproduct").each(function() {
var extra_price = $(this).data('price');
var quantity = $('.extraQuantity', this).val();
//Total for one product
var subtotal = extra_price*quantity;
//Round to 2 decimal places.
subtotal = subtotal.toFixed(2);
//Display subtotal in HTML element
$('.productTotal', this).html(subtotal);
});
// total
$('.productTotal').each(function() {
sum += Number($(this).html());
});
$('#sum').html(sum.toFixed(2));
};
//Update total when quantity changes
$(".extraQuantity").bind("keyup change", function() {
updateTotal();
});
//Update totals when page first loads
updateTotal();
// set this from local
$('span.productTotal').each(function() {
$(this).before("£")
});
// unit price
$('.extraproduct span').each(function() {
var $price = $(this).parents("div").data('price');
$(this).before($price);
});
$('input[type="checkbox"]').change(function(){
var totalprice = 0;
$('input[type="checkbox"]:checked').each(function(){
totalprice= totalprice + parseInt($(this).val());
});
$('#fittingprice').val(totalprice);
});
// THE BIT THAT SHOULD OUTPUT THE SUM OF THE 3 TOTALS
$("span, .sumthree").change(function(){
var finalquote = 0;
$(".sumthree").each(function() {
finalquote = finalquote + parseInt($(this).html());
});
$('#quotefinal').val(finalquote);
console.log(finalquote);
});
});
})(jQuery)
I've cut down the HTML so it's a bit more understandable. I've included a JSFiddle to see the full code if needed. https://jsfiddle.net/DigitalAdam/c2jpawy4/2/
If you think I need to cut the JS down more, please let me know and I'll see what I can do. I'm new to doing calculators in Jquery and due to the nature of the calculator the above code all seemed relevant to me.
Regards
From what I remember JQuery's val() function returns a string. Try passing your values to parseInt() to get integers so you can do calculations.
parseInt($('#works-width').val()) etc...
Update: $('.variations_form').each block wraps most of your code. close it before you declare updateTotal to fix most functionality. Still working on the final though.

only the first row were calculated automatically using jquery

i have this table that has a column for the edit button. a modal will pop up and the data from the row selected will show when the button is clicked.
so on my edit modal, i have 3 textboxes: Quantity, Consumed, and Available.
$('#edit-quant').keyup(function() {
var quant;
var consumed;
quant = parseFloat($('#edit-quant').val());
consumed = parseFloat($('#edit-consumed').val());
avail = quant - consumed || 0;
$("#edit-avail").val(avail);
});
$('#edit-consumed').keyup(function() {
var quant;
var consumed;
quant = parseFloat($('#edit-quant').val());
consumed = parseFloat($('#edit-consumed').val());
avail = quant - consumed || 0;
$("#edit-avail").val(avail);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input-group mb-3">
<span class="input-group-text" style="color: #008080"><label>Quantity</label></span>
<input class="form-control" type="text" id="edit-quant" name="edit-quant" placeholder="Quantity" value="2"></i>
<span class="input-group-text" style="color: #008080"><label>Consumed</label></span>
<input class="form-control" type="text" id="edit-consumed" name="edit-consumed" placeholder="Consumed" value="3">
<span class="input-group-text" style="color: #008080"><label>Available</label></span>
<input class="form-control" id="edit-avail" type="text" name="edit-avail" placeholder="Available" value="4" readonly>
</div>
and when i try to change the values of the Quantity and Consumed and calculates its Available. only the first row of the table were working. the proceeding rows remains the same. how can i fix this?
I assume you have these repeated. You should not have an id attribute that is the same on any two or more elements on the same page. When you select an element by its id, the first element found with that value is going to be returned.
What you can do is make these into classes, then to get the fields, you can find the .closest(".input-group") which is wrapping all of your fields. From there, you can pull any of the fields by their given class. Alternatively, just use the name attribute on the fields and get rid of the id all together.
<div class="input-group mb-3">
<span class="input-group-text" style="color: #008080"><label>Quantity</label></span>
<input class="form-control" type="text" name="edit-quant" placeholder="Quantity" value="{{$med->med_quantity}}" ></i>
<span class="input-group-text" style="color: #008080"><label>Consumed</label></span>
<input class="form-control" type="text" name="edit-consumed" placeholder="Consumed" value="{{$med->med_consumed}}">
<span class="input-group-text" style="color: #008080"><label>Available</label></span>
<input class="form-control" type="text" name="edit-avail" placeholder="Available" value="{{$med->med_available}}" readonly>
</div>
I've removed the id attributes from the three fields. Now, when our event triggers, we'll find the group (parent DIV), and get each field with .find().
$('input[name = "edit-quant"], input[name = "edit-consumed"]').keyup(function()
{
var $group = $(this).closest('.input-group');
var quant = parseFloat($group.find('input[name = "edit-quant"]').val());
var consumed = parseFloat($group.find('input[name = "edit-consumed"]').val());
$group.find('input[name = "edit-avail"]').val(quant - consumed || 0);
});
Untested, but should work for you, or at least get you on the right track.

associate number in number field with the number of newly created js div's

I have a set of number input fields, labeled small & medium.., and a set of div's with the label small and medium. When you add a number to the small number input field a text input insertsAfter the div labeled small. When you subtract a number from the small number input field, the text input field that was recently added is removed. the adding and removing of the text input is be the last one in the list. This same thing goes for the medium number field and medium label/textfield
please see JSFiddle for reference
http://jsfiddle.net/7PhJZ/53/
Right now my script is working correctly when I click the up or down buttons on the number field. But When I type in, for instance 5 in the small number field, only one new div/name input fields appears under the label small. I need the adding and subtracting of these input fields to be generated when I use the arrows and when I type in a number. So when I type in "5" 5 name/text input fields should appear under the associated label.
html :
<div id="product-1">
<div class="size-field">
<div id="size-label">s</div>
<div class="number-input">
<input id="Small" class="product-quantity" type="number" name="Small"
min="0" max="9999" data-product-id="1"></input>
</div>
</div>
<div id="size-label">m</div>
<div class="number-input">
<input id="Medium" class="product-quantity" type="number"
name="Medium" min="0" max="9999" data-product-id="1"></input>
</div>
<div class="name-number-header">
<h5>HEADER<h5></div>
<div class="name-number-field-container" data-size="Small">small:
</div>
<div class="name-number-field-container" data-size="Medium">medium:
</div>
</div>
<br clear="all">
<div id="product-2">
<div class="size-field">
<div id="size-label">s</div>
<div class="number-input">
<input id="Small" class="product-quantity" type="number" name="Small"
min="0" max="9999" data-product-id="2"></input>
</div>
</div>
<div id="size-label">m</div>
<div class="number-input">
<input id="Medium" class="product-quantity" type="number" name="Medium"
min="0" max="9999" data-product-id="2"></input>
</div>
<br clear="all">
<div class="name-number-header"><h5>HEADER<h5></div>
<div class="name-number-field-container" data-size="Small">small:
</div>
<div class="name-number-field-container" data-size="Medium">medium:
</div>
</div>
js :
$('.product-quantity').each(function () {
$(this).data('val', this.value);
}).on('change', function () {
var val = $(this).val(),
old = $(this).data('val'),
input = $('<div/>', {'class': 'name-number-field'}).html('<input
class="name-field" name="name" placeholder="Name" type="text">'),
ele = $(this).closest('[id^="product"]').find('[data-size="' + this.name + '"]'),
inc = val >= old;
if (inc) {
$(input).insertAfter(ele.nextUntil(':not(.name-number-field)').last()
.length ? ele.nextUntil(':not(.name-number-field)').last() : ele);
} else {
ele.nextUntil(':not(.name-number-field)').last().remove();
}
$(this).data('val', this.value);
});
See this fiddle
You need to put a for loop outside the code that created the elements:
}).on('change', function () {
var val = $(this).val(),
old = $(this).data('val');
for (var count=0; count<Math.abs(val-old) ; count++)
{
...
}
Update based on comments
See this updated fiddle. There were some problems that were in the original code:
The data was not initialised. Fix: if( !startVal || startVal.length == 0 )
The comparison was not with ints. Fix: inc = (parseInt(val) >= parseInt(old));
Your code is checking for the direction of change between old and new only, not how much difference there is. If it's an increase (of any amount), you add an element; if it's a decrease, you remove one.
You need to wrap that code in a loop and execute it as many times as the difference between old and new.
for (var i=0 ; i<Math.abs(val-old) ; i++) {
if (inc) {
$(input).insertAfter(ele.nextUntil(':not(.name-number-field)').last()
.length ? ele.nextUntil(':not(.name-number-field)').last() : ele);
} else {
ele.nextUntil(':not(.name-number-field)').last().remove();
}
}

Categories