Problems With Making Things Dynamic - javascript

Everything Works Fine if I create a duplicate Manually, But when I try to duplicate elements using j-query the function doesn't work except on the original created entry.The first input tag has a auto-complete source linked with the class that also only works with the original elements and not with the clones.
<div class="row add">
<form id="form1" action="#">
<input class="col-md-offset-1 col-xs-3 inpro clac" id="inpro1">
<input class="col-xs-1 mrp calc" id="mrp1">
<input class="col-xs-1 qt calc" id="qt1">
<input class="col-xs-1 dis calc" id="dis1">
<div class="col-xs-2 amt calc" id="amt1"></div>
<input type="submit" class="sub" id="sum1">
</form>
</div>
<button class="row col-md-offset-1 col-xs-1 add" id="copy">Add</div>
</div>
<script>
$('.calc').blur(function(e){
var k = this.id.substr(this.id.length-1);
var mrp = parseFloat( $('#mrp'+k).val() );
var qt = parseFloat( $('#qt'+k).val() );
var di = $('#dis'+k).val();
var dis = parseFloat( di );
var disc = di.substr(di.length-1);
var amt = "";
if (mrp>0 && qt>0 && dis>0) {
if (disc === "%") {
amt = mrp*qt - mrp*qt*dis/100;
} else {
amt = mrp*qt - dis;
}
var amount = "Rs."+ " " + Math.round( amt ) + " "+ "/-";
}
$('#amt'+k).html(amount);
e.preventDefault();
});
var scale = $("#copy").click(function() {
var add = $(".add");
var cnt = add.length + 1;
add.eq(0).clone().insertBefore(this)
.find("form").attr("id", "form" + cnt)
.find("input, div").each(function() {
this.id = this.id.replace(/\d+/, cnt);
if ($(this).is('div')) {
$(this).text = $(this).text("");
} else {
this.value = null;
}
});
});
</script>
Here is the fiddle http://jsfiddle.net/UwMML/

I have edited the fiddle,
You have to have the binding function separate, because you will have to use that to bind blur event each time you add a set of input fields. In your code, blur event is bound to .calc only one time.
This part will do the first event binding
$(document).ready(function(){
reBind();
});
For each time you click on Add button, this function will get executed. It will unbind all the prior bindings (to make the DOM overhead minimize) and re-bind blur event to all .calc inputs
function reBind(){
$('.calc').unbind("blur").blur(function(e){
var k = this.id.substr(this.id.length-1);
var mrp = parseFloat( $('#mrp'+k).val() );
var qt = parseFloat( $('#qt'+k).val() );
var di = $('#dis'+k).val();
var dis = parseFloat( di );
var disc = di.substr(di.length-1);
var amt = "";
if (mrp>0 && qt>0 && dis>0) {
if (disc === "%") {
amt = mrp*qt - mrp*qt*dis/100;
} else {
amt = mrp*qt - dis;
}
var amount = "Rs."+ " " + Math.round( amt ) + " "+ "/-";
}
$('#amt'+k).html(amount);
e.preventDefault();
});
}

You need to reinitialize your calc function after the new elements have been added:
function calc() {
$('.calc').blur(function (e) {
var k = this.id.substr(this.id.length - 1);
var mrp = parseFloat($('#mrp' + k).val());
var qt = parseFloat($('#qt' + k).val());
var di = $('#dis' + k).val();
var dis = parseFloat(di);
var disc = di.substr(di.length - 1);
var amt = "";
if (mrp > 0 && qt > 0 && dis > 0) {
if (disc === "%") {
amt = mrp * qt - mrp * qt * dis / 100;
} else {
amt = mrp * qt - dis;
}
var amount = "Rs." + " " + Math.round(amt) + " " + "/-";
}
$('#amt' + k).html(amount);
e.preventDefault();
});
}
calc();
var scale = $("#copy").click(function () {
var add = $(".add");
var cnt = add.length + 1;
add.eq(0).clone().insertBefore(this)
.find("form").attr("id", "form" + cnt)
.find("input, div").each(function () {
this.id = this.id.replace(/\d+/, cnt);
if ($(this).is('div')) {
$(this).text = $(this).text("");
} else {
this.value = null;
}
});
calc();
});
FIDDLE

Related

All buttons only affect one input instead of respective input

I am making a little project for my self. So basically its main function is to create a base counter for each game.
For example: If there are two players it should create three bases. (This is for the card game "smash up" if that helps you understand better.) But when the Buttons populate they all only effect the last input. I can not figure out how to make them effect their respective inputs.
The problem I am having is that every button I click only effects the last input.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type = "text" placeholder = "How many players?">
<button id = "enter" onclick = "baseMaker()">
Enter
</button>
</div>
<p></p>
</body>
</html>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function baseMaker()
{
for(var i = 0; i <= input.value; i++)
{
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement( "input");
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
This is a common thing to run into especially when not using a framework in javascript.
I am not sure why this happens but when a function is defined directly in a loop, the closure for these created functions becomes whatever it is after the last iteration. I believe it is because the closure for each callback function is only "sealed up" (for lack of a better word) at the end of the loop-containing-function's execution which is after the last iteration. It's really beyond me, though.
There are some easy ways to avoid this behavior:
use bind to ensure a callback gets called with the correct input (used in solution at bottom)
create a function which creates a handler function for you and use that in the loop body
function createIncrementHandler(input, howMuch){
return () => input.valueAsNumber += howMuch;
}
/// then in your loop body:
downButton.addEventListener('click', createIncrementHandler(score, 1));
get the correct input by using the event parameter in the handler
downButton.addEventListener('click', (event) => event.target.valueAsNumber += 1);
make the entire body of the loop into a function, for example:
function createInputs(i) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
Here is a full example of one of the possible fixes.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type="text" placeholder="How many players?">
<button id="enter" onclick="baseMaker()">
Enter
</button>
</div>
<p></p>
<script>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function incrementInput(input, byHowMuch) {
input.valueAsNumber = input.valueAsNumber + byHowMuch;
}
function baseMaker() {
for (var i = 0; i <= input.value; i++) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement("button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', incrementInput.bind(null, score, 1));
//downbutton
var downButton = document.createElement("button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', incrementInput.bind(null, score, -1));
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
</script>
</body>
</html>
I will do that this way :
const
AllBases = document.querySelector('#bases')
, bt_Start = document.querySelector('#game-go')
, bt_newGame = document.querySelector('#new-game')
, playerCount = document.querySelector("#play-start > input")
;
playerCount.value = ''
playerCount.focus()
playerCount.oninput = () =>
{
playerCount.value.trim()
bt_Start.disabled = (playerCount.value === '' || isNaN(playerCount.value))
playerCount.value = (bt_Start.disabled) ? ''
: (playerCount.valueAsNumber > playerCount.max) ? playerCount.max
: (playerCount.valueAsNumber < playerCount.min) ? playerCount.min
: playerCount.value
}
bt_newGame.onclick = () =>
{
playerCount.value = ''
playerCount.disabled = false
bt_Start.disabled = true
bt_newGame.disabled = true
AllBases.innerHTML = ''
playerCount.focus()
}
bt_Start.onclick = () =>
{
playerCount.disabled = true
bt_Start.disabled = true
bt_newGame.disabled = false
for(let i = 0; i <= playerCount.valueAsNumber; i++)
{
let base = document.createElement('p')
base.countValue = 20 // create a counter property on <p>
base.innerHTML = `Base ${i+1} : <span>${base.countValue}</span> <button>+</button> <button>−</button>\n`
AllBases.appendChild(base)
}
}
AllBases.onclick = ({target}) =>
{
if (!target.matches('button')) return // verify clicked element
let countElm = target.closest('p')
if (target.textContent==='+') countElm.countValue++
else countElm.countValue--
countElm.querySelector('span').textContent = countElm.countValue
}
#bases p span {
display : inline-block;
width : 6em;
border-bottom : 2px solid aqua;
padding-right : .2em;
text-align : right;
margin : 0 .3em;
}
#bases p button {
width : 2em;
margin : 0 .1em;
cursor : pointer;
}
<hr>
<hl> Score Keeper </h1>
<hr>
<div id="play-start" >
<input type="number" placeholder="How many players?" min="2" max="4">
<button id="game-go" disabled> Enter </button>
<button id="new-game" disabled> new </button>
</div>
<hr>
<div id="bases"></div>
If it helps, I can add more explanations

On mouse hover, display the corresponding sizes of bars, as mentioned in the input field

function draw() {
var nums = document.getElementById("number").value.split(",");
console.log(nums);
var w = 40;
var factor = 20;
var n_max = Math.max.apply(parseInt, nums);
var h_max = factor * n_max;
console.log("h max is " + h_max);
console.log("n max is " + n_max);
//var h_max = Math.max(h);
//var a = parseInt(nums);
//var create = document.getElementById("shape");
for (var i = 0; i <= nums.length; i++) {
//var x = parseInt(nums[i]);
//var final_width = w / x;
var x_cor = (i + 1) * w;
//var y_cor = i * w * 0.5;
var h = factor * nums[i];
console.log(x_cor);
console.log(h);
//console.log(h_max);
var change = document.getElementById("histContainer");
//change.className = 'myClass';
var bar = document.createElement("div");
bar.className = 'myClass';
//var c_change = document.createElement("div2");
//change.appendChild(c_change);
change.appendChild(bar);
console.log(change);
//change.style.x.value = x_cor;
//change.style.y.value = y_cor;
bar.style.position = "absolute";
bar.style.top = (h_max - h) + "px";
//bar.style.transform = "rotate(-1deg)"
bar.style.left = i * w * 1 + "px";
bar.style.backgroundColor = "rgb(1,211,97)";
bar.style.opacity = "0.6";
bar.style.width = w + "px";
bar.style.height = h + "px";
//var color1 = document.getElementById("histContainer");
//var bar_color = document.createElement("div");
//color1.appendChild(change);
//bar.style.color = "rgba(1,211,97,0.6)";
}
}
function color() {
//draw();
var change1 = document.getElementsByClassName('myClass');
for (var i = 0; i < change1.length; i++) {
change1[i].style.backgroundColor = "rgb(255,0,27)";
console.log("Change1 = " + change1[i]);
}
// var bar1 = document.createElement("div2");
// change1.appendChild(bar1);
// console.log(change1);
//change1.style.backgroundColor = "rgb(1,,254,16)";
}
$(document).ready(function() {
$(document).on("mouseover", ".myClass", function() {
//var number = this.nums;
//$(this.nums).text($(this.nums).index());
//$(".myClass").append(nums);
var shade = $(this).css("opacity");
$(this).css("opacity", "1.0");
$(document).on("mouseout", ".myClass", function() {
$(this).css("opacity", shade);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
Number:<input type="text" id="number" /><br>
<input type="button" id="button1" value="Draw" onClick="draw()" /><br>
<input type="button" id="button2" value="Change Color" onClick="color()" /><br>
<div id="histContainer" style="position: relative;"> </div>
<!-- <label for="mouseover" id="label1">Bar Value</label><br>
<input type="text" name="mouseover" id="text2" value="0"/><br> -->
<!-- <input type="button" id="color_change" style="float: right;" value="Change Color" /> -->
My Question is- I have entered some numbers as Input, and corresponding histogram is made according to the input values. Now, I have created mouseover() on each bar, and WANT to display their proportionate sizes, as given in input.
Can you provide me some help? Only thing which i figured out was- I have to call my draw function in the jQuery mouseover.
REFER TO the draw() and jQuery function(last)
I have figured out the answer. It is required that the nums array has to be re-declared again.
Solution Achieved
$(document).ready(function() {
$(document).on("mouseover",".myClass", function(){
//var numbers = $("#number").serialize();
//var number = this.nums;
var nums = document.getElementById("number").value.split(",");
$(this).text(nums[$(this).index()]);
//$(".myClass").append(nums);
var shade = $(this).css("opacity");
$(this).css("opacity", "1.0");
$(document).on("mouseout",".myClass", function() {
$(this).css("opacity", shade);
});
});
});

My variable refused to display in my Div

The country is changing along side the shipping. I could alert my shipping but will refuse to display in my div. What could be wrong? All calculations working well and displays well except for the #usashipping please help. My country changes and give the correct value for the calculation. The shipping fee just will not display.
<!-- language: lang-js -->
<script type="application/javascript">
var price= "";
var userprice="";
var flpay='';
var total='';
var shipping='';
var fees=30.0;
$('#country').change(function() {
var input = $(this).val();
var shipping;
if (input == 40) {
shipping = 10.0;
$('#usashipping').html('10.0');
} else if (input == 236) {
shipping = 10.0;
$('#usashipping').html('10.0');
} else {
shipping = 30.0;
$('#usashipping').html('30.0');
}
if(fees=='') {
$('#fees').html(30);
}
if(flpay=='')
{
$('#flpay').html(2*19.99);
}
if(total=='')
{
var tot=19.99*2.0 +30.0 + shipping;
var total= tot.toFixed(2);
$('#total').html(total);
}
$('.add').click(function() {
var $input = $(this).next();
var currentValue = parseInt($input.val());
var newinput= currentValue + 1;
$('#gems').val(newinput);
(newinput);
if(newinput==1)
{
var np1=(19.99*2.0);
flpay= np1.toFixed(2);
$('#flpay').html(flpay);
var tot= (fees + shipping + flpay);
var total= tot.toFixed(2);
$('#total').html(total);
var newp=19.99;
var price= newp.toFixed(2);
$('#price').html(price);
useprice= 19.99;
}
else if(newinput>1)
{
//useprice=useprice;
var newprice= 19.99 + (9.99*(newinput-1));
var np1 =(2*newprice);
var flpay = np1.toFixed(2);
$('#flpay').html(flpay);
var tot =( fees + shipping + (2*newprice) );
var total= tot.toFixed(2);
$('#usashipping').html(shipping);
$('#total').html(total);
var newp= newprice.toFixed(2);
$('#price').html(newp);
}
// newprice= price * 2;
// $('#price').html(newprice);
});
<!-- language: lang-html -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div>
First & Last Months Payment = $<span data-first-last-month-fees="" id="flpay"></span>
</div>
<div>
Shipping Fee = $<span data-shipping-fee="" id="usashipping"></span>
</div>
<div>
Total due today : $<span data-total-due="" id="total"></span>
</div>
Your code should work perfectly, but there are few things that you could improve in your code:
Instead of declaring shipping variable 3 times in each condition, you need to declare it only once, then update it in each condition, and make sure it's stored as a string so it can be displayed correctly in your HTML.
Instead of updating the HTML content of your span in every condition, just update it with the shipping amount in the end.
This is how should be your code:
$('#country').change(function() {
var input = $(this).val();
var shipping;
if (input == 40) {
shipping = '10.0';
} else if (input == 236) {
shipping = '20.0';
} else {
shipping = '30.0';
}
$('#usashipping').html(shipping);
});
Demo:
$('#country').change(function() {
var input = $(this).val();
var shipping;
if (input == 40) {
shipping = '10.0';
} else if (input == 236) {
shipping = '20.0';
} else {
shipping = '30.0';
}
$('#usashipping').html(shipping);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<select id="country">
<option value="40">40</option>
<option value="236">236</option>
<option value="100">100</option>
</select>
<div>
Shipping Fee = $<span data-shipping-fee="" id="usashipping"></span>
</div>
I can see error showing in your code. I found "$('.add').click" inside "$('#country').change". Also "$('#country').change" function you declared local variable "var shipping;" that's why no change on global "shipping;" value but you using it inside "$('#country').change" function. I modified little bit now try with following code and comment reply if not work for you:
var price= "";
var userprice="";
var flpay='';
var total='';
var shipping='';
var fees=30.0;
$('#country').change(function() {
var input = $(this).val();
if (input == 40) {
shipping = 10.0;
$('#usashipping').html('10.0');
} else if (input == 236) {
shipping = 10.0;
$('#usashipping').html('10.0');
} else {
shipping = 30.0;
$('#usashipping').html('30.0');
}
if(fees=='') {
$('#fees').html(30);
}
if(flpay=='')
{
$('#flpay').html(2*19.99);
}
if(total=='')
{
var tot=19.99*2.0 +30.0 + shipping;
var total= tot.toFixed(2);
$('#total').html(total);
}
})
$('.add').click(function () {
var $input = $(this).next();
var currentValue = parseInt($input.val());
var newinput = currentValue + 1;
$('#gems').val(newinput);
(newinput);
if (newinput == 1) {
var np1 = (19.99 * 2.0);
flpay = np1.toFixed(2);
$('#flpay').html(flpay);
var tot = (fees + shipping + flpay);
var total = tot.toFixed(2);
$('#total').html(total);
var newp = 19.99;
var price = newp.toFixed(2);
$('#price').html(price);
useprice = 19.99;
}
else if (newinput > 1) {
//useprice=useprice;
var newprice = 19.99 + (9.99 * (newinput - 1));
var np1 = (2 * newprice);
var flpay = np1.toFixed(2);
$('#flpay').html(flpay);
var tot = (fees + shipping + (2 * newprice));
var total = tot.toFixed(2);
$('#usashipping').html(shipping);
$('#total').html(total);
var newp = newprice.toFixed(2);
$('#price').html(newp);
}
// newprice= price * 2;
// $('#price').html(newprice);
})
I only changed the div id from #usashipping to something else and it works just fine. Maybe #usashippingis now a constant in jquery library.

jQuery slider with input value on drag after refresh

I've found this grate slider which is combo of 4 sliders sharing 100% value. Problem is that it doesn't pick value of input, yet it resets to 25% for each slider every time page is refreshed. Can someone help by making slider picking value of inputs before they determine position of slider knob.
HTML
<div align="center" class="title">Statistiche:</div>
<div id="outer_container">
<div id="container">
<span class='multislider'>Hokuto ShinKen (<input type='text' required name='question_3' class='amount' value='5' data-min='0' data-max='100'/>)
<div class='slider tied'>
</div>
Nanto (<input type='text' required name='question_3' class='amount' value='15' data-min='0' data-max='100'/>)
<div class='slider tied'>
</div>
Gento (<input type='text' required name='question_3' class='amount' value='50' data-min='0' data-max='100'/>)
<div class='slider tied'>
</div>
Artiglio del Monte Taishan (<input type='text' required name='question_3' class='amount' value='30' data-min='0' data-max='100'/>)
<div class='slider tied'></div>
</span>
</div>
</div>
jQuery
var init = true;
var elements = $(".multislider").children(".slider.tied").length;
var MAX = 100;
var inpVal = $('.txt_name').val();
var initValue = (inpVal) >> 0;
//var initValue = (MAX / elements) >> 0;
var InitMod = MAX % elements;
$(".slider.tied").each(function() {
var slidersTied = $(".slider.tied");
var context = $(this);
var input = context.prev(".amount");
var val = input.data('answer');
var min = input.data('min');
var max = input.data('max');
var range = 1;
var proceed = false;
$(this).empty().slider({
value: val,
min: min,
max: max,
range: range,
animate: "slow",
create: function(event, ui){
if (InitMod > 0) {
$(this).slider('value', initValue + 1);
$(this).prev('.amount').val(initValue + 1);
InitMod = InitMod - 1;
}
else
{
$(this).slider('value', initValue);
$(this).prev('.amount').val(initValue);
}
},
slide: function(e, ui) {
// Update display to current value
$(this).prev('.amount').val(ui.value);
var current = ($(this).index() / 2) >> 0;
var total = 0;
var counter = 0
slidersTied.not(this).each(function() {
total += $(this).slider("option", "value");
counter += 1;
});
total += ui.value;
if (total != MAX){
proceed = true;
}
var missing = MAX - total;
console.log("missing: " + missing);
counter = 0;
if(proceed) {
//carico vettore elementi
var elements = [];
slidersTied.each(function() {
elements[counter] = $(this);
counter += 1;
});
var endIndex = counter - 1;
counter = endIndex + 1;
while (missing != 0) {
console.log("current counter: " + counter);
do {
if (counter == 0)
{
counter = endIndex;
}
else
{
counter = counter - 1;
}
} while(counter == current)
console.log("elemento attuale: " + counter);
var value = elements[counter].slider("option", "value");
var result = value + missing;
if (result >= 0)
{
elements[counter].slider('value', result);
elements[counter].prev('.amount').val(result);
missing = 0;
}
else
{
missing = result;
elements[counter].slider('value', 0);
elements[counter].prev('.amount').val(0);
}
}
}
}
});
});
Example
http://jsfiddle.net/vuQz5/116/
Thanks
There are two issues, var val = input.data('answer'); is wrong, there is no such data value what you need is to get the input value like this:
var val = input.val();
val = (val) ? val : 0;
and also use that value in create method instead of initValue there is no need for if condition you only need whatever is in the else clause:
$(this).slider('value', val);
$(this).prev('.amount').val(val);
Check this fiddle

How can I copy this function but with preset values?

Currently when a button is clicked, it subtracts an inputted value. I want to have a preset value subtracted once a preset button is clicked. It would also be perferable that I could reuse a function later on a different button with different values like so:
var preset = function(val1, val2, val3, val4) {
//function to subtract from current values
}
$('presetButton').click(function(){
preset(1,2,3,4)
}
Here is the current function as I have it. The first button function works, but I wanted to copy it into a preset button with preset values. The function would not include $(this) because the button would not be in the same wrapper div and are not siblings.
$(document).ready(function(){
$('button').click(function(){
var $button = $(this);
var subtract = parseInt($button.siblings('input').val(), 10);
var $currentP = $button.siblings('.number').children('p');
var current = parseInt($currentP.text(), 10);
var newVal = current - subtract;
var $history = $button.siblings('.wrap').children('.history');
if (isNaN(subtract)) {
alert("Please enter in a number");
} else {
$currentP.effect('bounce', function() {
$currentP.text(newVal);
$(this).show();
});
$history.append("<p>"+subtract+"</p>");
}
});
$('#presets').click(function(){
//set up the subtracting and current variables
var subCal = 120;
var subPro = 24;
var subCarbs = 3;
var subFat = 1;
//retrieve current number then convert to a number
var toNum = function(id) {
return parseInt($(id + ' .number').children('p').text(), 10);
}
var curCal = toNum('#calories');
var curPro = toNum('#protein');
var curCarbs = toNum('#carbs');
var curFat = toNum('#fats');
//create new values
var newCal = curCal - subCal;
var newPro = curPro - subPro;
var newCarbs = curCarbs - subCarbs;
var newFat = curFat - subFat;
//apply new values
var applyNew = function(id, newVal) {
$(id + ' .number p').text(newVal)
}
applyNew('#calories', newCal);
applyNew('#protein', newPro);
applyNew('#carbs', newCarbs);
applyNew('#fats', newFats);
//Add to presets to history
})
});
The HTML
<h1>Track your Macros</h1>
<div class="wrapper">
<div id="calories">
<div class="number"><p>1945</p></div>
<div class="label"><p>Calories</p></div>
<input type="text"></input>
<button>Subtract</button>
<div class="wrap">
<div class="history"></div>
</div>
</div>
<div id="protein">
<div class="number"><p>200</p></div>
<div class="label"><p>Protein</p></div>
<input type="text"></input>
<button>Subtract</button>
<div class="wrap">
<div class="history"></div>
</div>
</div>
<div id="carbs">
<div class="number"><p>173</p></div>
<div class="label"><p>Carbs</p></div>
<input type="text" class="subtract"></input>
<button>Subtract</button>
<div class="wrap">
<div class="history"></div>
</div>
</div>
<div id="fats">
<div class="number"><p>50</p></div>
<div class="label"><p>Fats</p></div>
<input type="text" class="subtract"></input>
<button>Subtract</button>
<div class="wrap">
<div class="history"></div>
</div>
</div>
</div>
<div id="presets"><img src="on-logo.png"></div>
Try
$(document).ready(function(){
$('button').click(function(){
var $button = $(this);
var subtract = parseInt($button.siblings('input').val(), 10);
var $currentP = $button.siblings('.number').children('p');
var current = parseInt($currentP.text(), 10);
var newVal = current - subtract;
var $history = $button.siblings('.wrap').children('.history');
if (isNaN(subtract)) {
alert("Please enter in a number");
} else {
$currentP.effect('bounce', function() {
$currentP.text(newVal);
$(this).show();
});
$history.append("<p>"+subtract+"</p>");
}
});
var preset = function(val1, val2, val3, val4) {
//set up the subtracting and current variables
var subCal = val1;
var subPro = val2;
var subCarbs = val3;
var subFat = val4;
//retrieve current number then convert to a number
var toNum = function(id) {
return parseInt($(id + ' .number').children('p').text(), 10);
}
var curCal = toNum('#calories');
var curPro = toNum('#protein');
var curCarbs = toNum('#carbs');
var curFat = toNum('#fats');
//create new values
var newCal = curCal - subCal;
var newPro = curPro - subPro;
var newCarbs = curCarbs - subCarbs;
var newFats = curFat - subFat;
//apply new values
var applyNew = function(id, newVal) {
$(id + ' .number p').text(newVal);
}
//apply new values
var applyHistory = function(id, val) {
$(id + ' .history').append("<p>" + val + "</p>");
}
applyNew('#calories', newCal);
applyNew('#protein', newPro);
applyNew('#carbs', newCarbs);
applyNew('#fats', newFats);
applyHistory('#calories', subCal);
applyHistory('#protein', subPro);
applyHistory('#carbs', subCarbs);
applyHistory('#fats', subFat);
}
$('#presets').click(function(){
preset(120,24,3,1);
})
});
Demo: Fiddle

Categories