-2

How would you solve?

Macros:

  • 1g of protein = 4cal
  • 1g of carbs = 4cal
  • 1g of fat = 9cal

Calorie limit = 1000cal

initially i get 3 input fields, 1 for each macro split like this.

  • input for protein value = 100g (40% of cals)
  • input for carbs value = 100g (40% of cals)
  • input for fat value 22g (20% of cals)

What i need to do is, if i edit any of the input gram value, the neighbour inputs change values to facilitate my change and the total grams still add up to 100% of my calorie limit.

I need a solution in JS /jQuery. Here is a starter template you may find useful.

http://jsbin[--DOT--]com/gaqugiwebo/2/edit?html,js,console,output

eliHimself
  • 77
  • 1
  • 9
  • 3
    Stack Overflow is not a code writing service. If you run into any issues while coding this yourself, we will be happy to help that that time. – amflare Mar 15 '18 at 14:06

2 Answers2

1

You could make something like this: a = input1 + input2 + input3 And the make this calculation: %input1 = (input1 * 100) / a. But I'm agree with @amflare you could try harder. The problem was basic math.

function calculatePorc() {
  // calculate total
  var total = 0;
  for(var i = 1; i < 4; i++) {
    total += parseInt($('input'+i).val()) || 0
  }

  // calculate porcetage
  for(i = 1; i < 4; i++) {
    var current = parseInt($('input'+i).val()) || 0;
    var porc = (current * 100) / total || 0;
  }
}

Here is a JSFIDDLE

finw3
  • 453
  • 5
  • 10
0

There are other jQuery-based options for 3-way inputs that "must always equal 100%".

A couple I've played with:


jQuery UI range slider

A jQuery-UI range slider with multiple handles, like this: (from my answer here)

example

Demo snippet:

const dvRed=29.9, dvGreen=58.7; //defaults
var dvs=[dvRed, dvRed+dvGreen];

$(document).ready( function(){ //setup slider
  $('#slider').slider({
    min: 0,
    max: 100,
    step: 0.1,
    values: dvs,
    range: true,
    slide: function(event, ui) {
      $.each(ui.values, function(i, v) {
        updateSlider(); //update vals on change
      });
    }
  });
  updateSlider(); //initial update of vals
});

function updateSlider(){
  //get slider values
  var R=Math.round($('#slider').slider('values')[0]*10)/10,
    B=Math.round((100-$('#slider').slider('values')[1])*10)/10,
    G=Math.round(((100-(R+B)))*10)/10;

  //set slider track to 3 colors
  $('.ui-slider').css('background','linear-gradient(90deg, red 0% '+R+'%, green '+R+'% '+(G+R)+'%, blue '+(G+R)+'% 100%');

  //center labels between handles
  $('#val1').html(R+'%').css('left',R/2+'%');
  $('#val2').html(G+'%').css('left',R+(G/2)+'%');
  $('#val3').html(B+'%').css('left',R+G+(B/2)+'%');

  //set body background color
  var bg='rgb('+R*2.55+','+G*2.55+','+B*2.55+')';
  $(document.body).css('background', bg);
}
    body{ font-family: Roboto, Helvetica, Arial, sans-serif; }
    #slider_cont{ position:relative; width:60vw; margin:5vh 20vw 10vh; }
    #slider{ width:100%; }
    #slider_vals{ width:100%; }
    #val1{ position:absolute; left:33%; color:red; }
    #val2{ position:absolute; left:50%; color:green; }
    #val3{ position:absolute; left:66%; color:blue; }
    .ui-slider-range { background:transparent !important;}
    .ui-slider{background-image:linear-gradient(90deg, red 0 40%, green 40% 60%, blue 60% 100%);}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" >
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

<div id='slider_cont'>
  <div id='slider'></div>
  <div id='slider_vals'>
    <div id='val1'></div>
    <div id='val2'></div>
    <div id='val3'></div>
  </div>
</div>

<div id='colors'></div>

Pie chart as control

Another option would be to use a pie chart as a control, either custom-built from SVG, or better yet, from an existing library such as Chart.js.

animated screenshot

Demo snippet:

var r=2990, g=5870, b=1140;
var step=150, lastHover=-1, adj;
var chart=document.getElementById('chart-area');
$('#rval').html(r); $('#gval').html(g); $('#bval').html(b);
var config = {
  type: 'pie',
  data: {
    datasets: [{
      data: [ r,g,b ],
      backgroundColor: [ '#f22','#1f1','#1e90ff' ],
      label: 'rgb'
    }],
    labels: ['R','G','B']
  },
  options: {
    legend: {display: false},
    animation: {
      duration: 200,
      easing: "easeOutQuart",
      onProgress : function(){ addLabels(this); }
    },
    responsive: true,
    tooltips: { enabled: false },
    onHover: function(e,i){
      if (typeof i[0]!=="undefined"){lastHover=(i[0]._index); }
    },
  }
};

chart.onmouseout=function(){lastHover=null;};
window.onload = function(){
  var ctx = chart.getContext('2d');
  window.myPie = new Chart(ctx, config);
};

chart.onwheel=(function(e) {  ///// wheel turned
  e.preventDefault();
  adj=(e.deltaY<0?step:-step);
  upd(lastHover,adj);
});

$('button').click( function() { ///// button clicked
  adj=(this.id.substr(1,2)=='up'?step:-step);
  var id=(['r','g','b']).indexOf(this.id.substr(0,1));
  upd(id, adj);
});

function upd(id, adj){
  var dd=config.data.datasets[0].data;
  /*subf*/function adjust(vChg, v2, v3){ var adj2=Math.round(((10000-(vChg+v2+v3))/(v2+v3))*v2); return[vChg, v2+adj2, 10000-(vChg+v2+adj2)]; }
  switch(id){
    case 0: [dd[0],dd[1],dd[2]]=adjust(dd[0]+adj,dd[1],dd[2]); break;
    case 1: [dd[1],dd[2],dd[0]]=adjust(dd[1]+adj,dd[2],dd[0]); break;
    case 2: [dd[2],dd[0],dd[1]]=adjust(dd[2]+adj,dd[0],dd[1]);
  } 
  [r,g,b]=dd;

  var prev_r=parseInt($('#rval').html()), //get values
   prev_g=parseInt($('#gval').html()),
   prev_b=parseInt($('#bval').html());
  if(r>prev_r){ $('#rup').css('background','red');} //hilite affected buttons
  else{if(r<prev_r){ $('#rdn').css('background','red');}}
  if(g>prev_g){ $('#gup').css('background','green');}
  else{if(g<prev_g){ $('#gdn').css('background','green');}}
  if(b>prev_b){ $('#bup').css('background','blue');}
  else{if(b<prev_b){ $('#bdn').css('background','blue');}}
  setTimeout(function(){clearButtonColors();},250);
  $('#rval').html(r/100); $('#gval').html(g/100); $('#bval').html(b/100);
  window.myPie.update();
}

function clearButtonColors(){ //reset button colors
  ['#rup','#rdn','#gup','#gdn','#bup','#bdn']
    .forEach(function(i){ $(i).css('background','transparent'); });
}

function addLabels(t){ //add chart labels
  var ctx = t.chart.ctx;
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  t.data.datasets.forEach(function (dataset) {
    for (var i = 0; i < dataset.data.length; i++) {
      if(dataset.data[i] != 0 ) { //no label when value is 0
        var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
            total = dataset._meta[Object.keys(dataset._meta)[0]].total,
            mid_rad = model.innerRadius+(model.outerRadius-model.innerRadius)/1.66,
            mid_ang = model.startAngle+(model.endAngle-model.startAngle)/2,
            x = mid_rad * Math.cos(mid_ang),
            y = mid_rad * Math.sin(mid_ang),
            pct=Math.round(dataset.data[i]/total*100);
        ctx.font = "10px Verdana";
        ctx.fillText(String(pct)+'%', model.x + x-3, model.y + y );
      }
    }
  });
}
body{font-size:16px; font-family:Helvetica;  padding:0; margin:0;}
#cancont{position:absolute;left:75px; width:225px;  height:10px; }
canvas {position:relative; right:0; }
button{height:25px; transition:all 500ms; }
button:hover{ transform:scale(1.15); background:springgreen; }
#rup,#gup,#bup{border-radius:0 50% 50% 0; }
#rdn,#gdn,#bdn{border-radius:50% 0 0 50%; }
#rup,#rdn{border-color:red;}
#gup,#gdn{border-color:green;}
#bup,#bdn{border-color:blue;}
table{ border-collapse:collapse; padding:0;  position:absolute; top:20px; }
td{text-align:center;}
tr{margin:100px 0;}
h4{ position:absolute; bottom:10px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id='cancont'>
  <canvas id="chart-area" ></canvas>
</div>

<div id='tblcont'>
  <table id='tbl'>
    <tr><td><button id='rdn'>- R</button></td>
      <td><div id='rval'></div></td>
      <td><button id='rup'>R +</button></td></tr>
    <tr><td><button id='gdn'>- G</button></td>
      <td><div id='gval'></div></td>
      <td><button id='gup'>G +</button></td></tr>
    <tr><td><button id='bdn'>- B</button></td>
      <td><div id='bval'></div></td>
      <td><button id='bup'>B +</button></td></tr>
  </table>
</div>
<h4>Adjust with RGB± buttons, or <u>use the mouse-wheel</u> over chart.</h4>
ashleedawg
  • 20,365
  • 9
  • 72
  • 105