Chartjs-Better looking function

0👍

Here’s a revised version of your code that shows how to accomplish what you’re trying to do. (I wasn’t sure what your barChart object looks like, so I substituted something relatively simple that should be close enough for demo purposes.)

Each button has a "data attribute" called number whose value gets passed to the changeTo function so the correct number of elements will be shown. (It’s fine, if you prefer, to use the changeTo function itself as the listener function instead of using a separate handleClick function that calls changeTo — you would just need to move handleClick‘s logic, including retrieving the number, to inside of changeTo.)

The code is shortened a bit further by putting the data arrays (newConfirmedCases, etc.) into an array of arrays, which parallels the barChart.data.datasets array of .data objects — this lets us copy (the desired part of) each data array into the corresponding .data object within a loop, according to its index (i) in datasets.

See the in-code comments for further clarifications. And look up anything you want to know more about on MDN (eg "data attributes", "arrow functions", "event listeners", or "foreach").

const
  // Simulates your barChart object for initial display
  barChart = getBarChart();

  // Simulates your data arrays
  newConfirmedCases =     [11, 22, 33, 44, 55],
  newConfirmedRecovered = [ 5, 10, 15, 20, 25],
  newConfirmedDeaths =    [ 1,  2,  3,  4,  5],
  formattedDates = ["1/1/21", "1/2/21", "1/3/21", "1/4/21", "1/5/21"],

  // Identifies relevant DOM elements
  buttonContainer = document.getElementById("buttonContainer");
  
  // Calls handler func when anything in buttonContainer is clicked
  buttonContainer.addEventListener("click", handleClick);
  
  // Triggers initial display of all data
  changeTo("Infinity");


  // Defines listener function
  function handleClick(event){ // Listener knows about triggering event
    const clickedThing = event.target; // Event has useful properties
    if(clickedThing.tagName != "BUTTON"){ return; } // Ignores irrelevant clicks

    // Gets number from custom attribute; passes it to `changeTo`
    changeTo(clickedThing.getAttribute("data-number"));
  }


  // Defines the function that does the heavy lifting
  function changeTo(howMany) {
    // - Takes a number (including JS's global "infinity")
    // - Updates barChart object, then updates display

    const
      // Simulates barChart object for local use
      barChart = getBarChart(),

      // Makes a `datasets` matrix (an array of arrays)
      datasets = [newConfirmedCases, newConfirmedRecovered, newConfirmedDeaths];

    // Applies an anonymous function to each array in matrix
    datasets.forEach( (dataset, i) => {

      const whereToSliceData = Math.max(dataset.length - howMany, 0);

      // Left side is the corresponding array from inside `barChart`
      // Right side is a slice of the current array from matrix
      barChart.data.datasets[i].data = dataset.slice(whereToSliceData);
    });

    // A similar process sets barChart's labels
    const whereToSliceDates = Math.max(formattedDates.length - howMany, 0);
    barChart.data.labels = formattedDates.slice(whereToSliceDates);

    // Finally, calls `.update` method to change the display
    barChart.update();
  }

  // Mostly ignore this, just simulates your barChart obj (poorly)
  function getBarChart(){
    const barChart = {
      data: {
        datasets: [{},{},{}],
        labels: []
      },
      update: function(){
        const display = document.getElementById("display");
        display.innerHTML = "";
        for (let dataset of this.data.datasets){
          for (let datum of dataset.data){
            const spaces = 8 - datum.toString().length;
            display.innerHTML += " ".repeat(spaces) + datum;
          }
          display.innerHTML += "<br/>";
        }
        display.innerHTML += "<br/>" + "&nbsp;".repeat(3);
        for (let label of this.data.labels){
          display.innerHTML += "&nbsp;".repeat(2) + label;
        }
      }
    }
    return barChart;
  }
#display{ font-family: monospace; }
<div id="buttonContainer">
  <button data-number="Infinity">Default</button>
  <button data-number="2">Last Two</button>
  <button data-number="3">Last Three</button>
  <button data-number="4">Last Four</button>
</div>
<hr/>
<div id="display"></div>

3👍

You could implement a solution that both cleans up and adds flexibility to your code, which is to create a single changeTo() function, taking as argument the number of days you would like to slice your newConfirmed... array.

Additionally, you could use a map to save the index of datasets as key and the corresponding newConfirmed... array as value.

Eventually, add the eventListeners by calling the changeTo() function for the amount of days you require.

//Key of map is dataset index, value is newConfirmed array
let map = new Map();
map.set(0, newConfirmedCases);
map.set(1, newComfirmedRecovered);
map.set(2, newConfirmedDeaths);

//This operation is done multiple times in your code, let's make it a function
function slicer(val, number) {
    return val.slice(Math.max(val.length - number, 0));
}

function changeTo(number = 0) {
    //Iterate through map and set data
    //If number is 0, whole array is returned, else the sliced array
    for (const [key, val] of map.entries()) 
        barChart.data.datasets[key].data = (number) ? slicer(val, number) : val;

    barChart.data.labels = (number) ? slicer(formattedDates, number) : formattedDates;
    barChart.update()
}

//Set eventListeners by calling changeTo() for the required amount of days
//Remember that if you give no argument, it will act like former changeToBeginning
document.getElementById("defaultState").addEventListener("click", changeTo());
document.getElementById("lastSeven").addEventListener("click", changeTo(7));
document.getElementById("lastThirty").addEventListener("click", changeTo(30));
document.getElementById("lastNinety").addEventListener("click", changeTo(90));

0👍

function updateUI() {
    updateStats();
    chartDrawing();
}

barChart = new Chart(chartTwo, {
        type: "bar",
        data: {
            datasets: [{
                    label: "Nowych Zarażeń",
                    data: newConfirmedCases,
                    fill: false,
                    borderColor: "gray",
                    backgroundColor: "crimson",
                    borderWidth: 1,
                },
                {
                    label: "Nowych Ozdrowień",
                    data: newConfirmedRecovered,
                    fill: false,
                    borderColor: "gold",
                    backgroundColor: "green",
                    borderWidth: 1,
                },
                {
                    label: "Nowych Zgonów",
                    data: newConfirmedDeaths,
                    fill: false,
                    borderColor: "brown",
                    backgroundColor: "coral",
                    borderWidth: 1,
                },
            ],
            labels: formatedDates,
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
        }
    })

The rest of a code, unfortunately i am getting "undefined" of barChart.data.
The chartDrawing function have all the code in itself.

Leave a comment