4

I'm trying to create a chart which uses an input set of data which I then turn into percentages so that the chart is always between the range of -100 and 100.

From the array of JSON data I want to work out the max number (positive value, generally) and min number (likely to be a negative but turned into a positive using a - before the variable).

I then want to work out which of those two 'positive' values is higher and mark that as the top value.

I then for each value from the data, want to divide the (timeline_value by the top_value) multiplied by 100 and rounded.

For each of those values, I need to add them to individual arrays. One of them is to calculate the rectangle width chartWidth, one to work out the rect start position chartStart (for positive values its 152, for negative values, it is 148 minus chartWidth).

For chartColor, I want to have it predefined that revenue is always green (#28CE6D), expenses is always red (#DF3456) and profit is always blue (#4DC7EC). Below is the data set that is driving my chart that I need to create from the input data:

var chartStart = [152, 84, 152]
var chartWidth = [100, 64, 36]
var chartNames = ["$7,110 Revenue", "$4,539 Expenses", "$2,571 Profit"]
var chartColor = ["#28CE6D", "#DF3456", "#4DC7EC"]

Here's the bit I'm stuck on where I'm trying to create the above set from. Thanks

var input_data = {
  timeline_balances: [
    {
      timeline_name: "Revenue",
      timeline_value: 7110,
      currency: "$"
    },
    {
      timeline_name: "Expenses",
      timeline_value: -4539,
      currency: "$"
    },
    {
      timeline_name: "Profit",
      timeline_value: 2571,
      currency: "$"
    }
  ]
}

var max_value = input_data.timeline_balances.timeline_value.max_value
var min_value = -input_data.timeline_balances.timeline_value.min_value

if (max_value > min_value) {
  top_value = max_value;
} else {
  top_value = min_value;
}
Titulum
  • 9,928
  • 11
  • 41
  • 79
Matt Lightbourn
  • 597
  • 3
  • 20

3 Answers3

4

You have to use a loop to get values from the object as the object is inside an array

var input_data = {
  timeline_balances: [{
      timeline_name: "Revenue",
      timeline_value: 7110,
      currency: "$"
    },
    {
      timeline_name: "Expenses",
      timeline_value: -4539,
      currency: "$"
    },
    {
      timeline_name: "Profit",
      timeline_value: 2571,
      currency: "$"
    }
  ]
}
var top_value=-10;
input_data.timeline_balances.forEach(e=>{
var max_value = e.timeline_value
var min_value = -1*e.timeline_value
if (max_value > min_value) {
if(max_value>top_value)
  top_value = max_value;
} else {
if(min_value>top_value)
  top_value = min_value;
}
})
console.log(top_value)
ellipsis
  • 12,049
  • 2
  • 17
  • 33
  • that is awesome, thank you for that. I need to work out how to then also loop through the values one by one and calculate their percentage and insert them into the array called chartWidth as per the calculation of (timeline_value / top_value) * 100. Is it pretty much the same as what you've done there already with a bit of modification? Thanks, Matt – Matt Lightbourn Feb 11 '20 at 06:44
  • yeah, that will do it – ellipsis Feb 11 '20 at 06:46
0

We can utilize a custom sort on the array. In our custom sort function we'll use Math.abs() to get the value regardless of sign and sort using that.

In the example below I've done the sort in descending order, so the first value in the array has the highest absolute value. (I've tweaked your negative value to make it our maximum for the purposes of this example)

var input_data = {
  timeline_balances: [{
      timeline_name: "Revenue",
      timeline_value: 7110,
      currency: "$"
    },
    {
      timeline_name: "Expenses",
      timeline_value: -14539,
      currency: "$"
    },
    {
      timeline_name: "Profit",
      timeline_value: 2571,
      currency: "$"
    }
  ]
}

/*Make a copy of the object as sort happens in place*/
/*See: https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript*/
var absolute_sorted_data = JSON.parse(JSON.stringify(input_data));
/*Sort by absolute value - decending*/
absolute_sorted_data.timeline_balances.sort(function(a,b){
  return Math.abs(b.timeline_value) - Math.abs(a.timeline_value);
});
/*First value has the highest absolute value*/
var max_val = Math.abs(absolute_sorted_data.timeline_balances[0].timeline_value);
console.log(max_val);

/*Update chart arrays - also set new properties in your object. 
  This is cleaner but your charting engine may not support that*/
var chartStart = []; //[152, 84, 152]
var chartWidth = []; //[100, 64, 36]
var chartNames = []; //["$7,110 Revenue", "$4,539 Expenses", "$2,571 Profit"]
var chartColor = []; //["#28CE6D", "#DF3456", "#4DC7EC"]
input_data.timeline_balances.forEach(function(el){
   var val = el.timeline_value;
   el.chartStart = val >= 0 ? 152 : 84;
   el.chartWidth = Math.round(val/max_val*100);
   el.chartName = `${el.currency}${Math.abs(val)} ${el.timeline_name}`;
   switch(el.timeline_name) {
      case "Revenue":
        el.chartColor = "#28CE6D";
        break;
        
      case "Expenses":
        el.chartColor = "#DF3456";
        break;
       
      case "Profit":
        el.chartColor = "#4DC7EC";
        break;
        
   }
   
  chartStart.push(el.chartStart);
  chartWidth.push(el.chartWidth);
  chartNames.push(el.chartName);
  chartColor.push(el.chartColor);
});

console.log(input_data);
Jon P
  • 19,442
  • 8
  • 49
  • 72
-1

{//

<script>
'use strict';

let input_data = 
{
   timeline_balances : 
    [
      {
              timeline_name : "Revenue",
        timeline_value : 7110,
        currency : "$"
            },
      {
              timeline_name : "Expenses",
        timeline_value : -4539,
        currency : "$"
            },
      {
              timeline_name : "Profit",
        timeline_value : 2571,
        currency : "$"
            }
  ]
};

let maxValue = 0;
let minValue = 0;

for (let key in input_data.timeline_balances) {

  {
      //alert(input_data.timeline_balances[key].timeline_value)

      if(maxValue < input_data.timeline_balances[key].timeline_value)
          maxValue = input_data.timeline_balances[key].timeline_value;

      if(minValue > input_data.timeline_balances[key].timeline_value)
          minValue = input_data.timeline_balances[key].timeline_value;
  }
} //end for loop

alert("Maximum value: " + maxValue);
alert("Minimum value: " + minValue);

//}
mds731
  • 56
  • 6