Categories
Chart.js

Chart.js — Scatter Chart and Fill Background

We can make creating charts on a web page easy with Chart.js.

In this article, we’ll look at how to create charts with Chart.js.

Scatter Chart

We can create a scatter chart with Chart.js

It’s a line chart with the x-axis changed to a linear axis.

For example, we can create one by writing:

var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'scatter',
  data: {
    datasets: [{
      label: 'Scatter Dataset',
      backgroundColor: 'green',
      data: [{
        x: -10,
        y: 0
      }, {
        x: 0,
        y: 10
      }, {
        x: 10,
        y: 5
      }]
    }]
  },
  options: {
    scales: {
      xAxes: [{
        type: 'linear',
        position: 'bottom'
      }]
    }
  }
});

We have the data property with an array of objects with the x and y properties.

x has the x coordinate, and y has the y coordinate on the chart.

The other properties are the same as the line chart.

We can get the options by going to https://www.chartjs.org/docs/latest/charts/line.html#dataset-properties.

Area Charts

Line and radar charts support the fill option instead of the dataset object which can be used to create an area between 2 datasets and the boundary.

We can add the fill with the fill property.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Monday', 'Tuesday', 'Wednesday'],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3],
      borderColor: 'green',
      fill: false,
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

to disable the fill with the fill property set to false .

Also, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Monday', 'Tuesday', 'Wednesday'],
    datasets: [{
        label: '# of foo',
        data: [12, 19, 3],
        borderColor: 'green',
        fill: '+2',
        borderWidth: 1
      },
      {
        label: '# of bar',
        data: [1, 4, 3],
        borderColor: 'red',
        fill: false,
        borderWidth: 1
      },
      {
        label: '# of baz',
        data: [2, 9, 13],
        borderColor: 'blue',
        fill: false,
        borderWidth: 1
      }

]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

to add fill between dataset 1 and dataset 3 with the '+2' option.

We’ll see the fill between the green and blue line.

The line color is set with the borderWidth property.

We can also set it to a negative number to make the fill between a later dataset and a dataset that’s added earlier.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Monday', 'Tuesday', 'Wednesday'],
    datasets: [{
        label: '# of foo',
        data: [12, 19, 3],
        borderColor: 'green',
        fill: false,
        borderWidth: 1
      },
      {
        label: '# of bar',
        data: [1, 4, 3],
        borderColor: 'red',
        fill: false,
        borderWidth: 1
      },
      {
        label: '# of baz',
        data: [2, 9, 13],
        borderColor: 'blue',
        fill: '-2',
        borderWidth: 1
      }

]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

We can also set fill to 'origin' to make the fill to the origin.

There’s also the propagate option that makes the fill area recursively extends to the visible target defined by the fill value of hidden dataset targets:

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Monday', 'Tuesday', 'Wednesday'],
    datasets: [{
        label: '# of foo',
        data: [12, 19, 3],
        borderColor: 'green',
        fill: false,
        borderWidth: 1
      },
      {
        label: '# of bar',
        data: [1, 4, 3],
        borderColor: 'red',
        fill: false,
        borderWidth: 1
      },
      {
        label: '# of baz',
        data: [2, 9, 13],
        borderColor: 'blue',
        fill: '-2',
        borderWidth: 1
      }

]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    },
    plugins: {
      filler: {
        propagate: true
      }
    }
  }
});

This way, if a dataset is hidden, then the fill will propagate to the nearest dataset that’s displayed.

Conclusion

We can create scatter charts and line charts will a fill background with Chart.js

Categories
Chart.js

Chart.js — Mixed Chart Types and Axes Options

We can make creating charts on a web page easy with Chart.js.

In this article, we’ll look at how to create charts with Chart.js.

Mixed Chart Types

We can have multiple chart types in one chart with Chart.js.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    datasets: [{
      label: 'Bar Dataset',
      data: [10, 20, 30, 40],
      backgroundColor: 'green'
    }, {
      label: 'Line Dataset',
      data: [50, 50, 50, 50],
      type: 'line',
      borderColor: 'blue'
    }],
    labels: ['January', 'February', 'March', 'April']
  },
});

We set the type to the 'line' so that we have one line chart and one bar chart within the same chart.

Drawing Order

The order that they’re drawn can also be changed.

The dataset are drawn so that the first one is topmost.

We can change that by setting the order property:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    datasets: [{
      label: 'Bar Dataset',
      data: [10, 20, 30, 40],
      backgroundColor: 'green',
      order: 2
    }, {
      label: 'Line Dataset',
      data: [20, 20, 20, 20],
      type: 'line',
      borderColor: 'blue',
      order: 1
    }],
    labels: ['January', 'February', 'March', 'April']
  },
});

Cartesian Axes

Cartesian axes are used by line, bar, and bubble charts.

4 cartesian axes are included in Chart.js by default.

They are linear, logarithmic, category, and time.

Axis ID

We can set the axis ID to set the ID of the axis.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      label: 'Line 1',
      data: [10, 20, 30, 40],
      backgroundColor: 'green',
      yAxisID: 'first-y-axis'
    }, {
      label: 'Line 2',
      data: [20, 20, 20, 20],
      backgroundColor: 'blue',
      yAxisID: 'second-y-axis'
    }],
    labels: ['January', 'February', 'March', 'April']
  },
  options: {
    scales: {
      yAxes: [{
        id: 'first-y-axis',
        type: 'linear'
      }, {
        id: 'second-y-axis',
        type: 'linear'
      }]
    }
  }
});

We set the id of the axes in the options object to set the axes to display.

Category Cartesian Axis

We can change the category cartesian axis.

We can change the minimum and maximum items to display.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      data: [10, 20, 30, 40, 50, 60]
    }],
    labels: ['January', 'February', 'March', 'April', 'May', 'June']
  },
  options: {
    scales: {
      xAxes: [{
        ticks: {
          min: 'March'
        }
      }]
    }
  }
});

Then the leftmost item is 'March' and 'January' and 'February' aren’t displayed.

Linear Cartesian Axis

We can change settings in the linear cartesian axis, which is the axis for displaying numerical data.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      label: 'First dataset',
      data: [0, 20, 40, 50]
    }],
    labels: ['January', 'February', 'March', 'April']
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          suggestedMin: 50,
          suggestedMax: 100
        }
      }]
    }
  }
});

We set the suggestedMin and suggestedMax properties to set the min and max values and it’s adjusted to fit the values.

If we have values in the dataset below 50 or higher than 100, then they’ll still be displayed.

Conclusion

We can set various options for the axes with Chart.js.

Categories
Chart.js

Chart.js — Doughnut/Pie, Polar Area, and Bubble Charts

We can make creating charts on a web page easy with Chart.js.

In this article, we’ll look at how to create charts with Chart.js.

Doughnut and Pie Charts

We can create a doughnut chart with the type set to 'doughnut' .

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'doughnut',
  data: {
    labels: ['Red', 'Blue', 'Yellow'],
    datasets: [{
      backgroundColor: ['red', 'blue', 'yellow'],
      data: [10, 20, 30]
    }]
  },
});

to create a doughnut chart with 3 colors.

The data is an array of numbers.

Dataset properties includes backgroundColor to change the background color.

borderAlign changes the alignment of the border.

borderColor changes the border color.

borderWidth changes the border width.

hoverBackgroundColor changes the color when we hover over the segments.

hoverBorder changes the segment’s color when we hover on it.

weight changes the weight.

The full list of options are at https://www.chartjs.org/docs/latest/charts/doughnut.html.

Polar Area

A polar area chart is similar to pie charts, but each segment has the same angle.

The radius of the segment is different according to the value.

To create one, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'polarArea',
  data: {
    labels: ['Red', 'Blue', 'Yellow'],
    datasets: [{
      backgroundColor: ['red', 'blue', 'yellow'],
      data: [10, 20, 30]
    }]
  },
});

We created a polar area chart with the type set to 'polarArea' .

Everything else is the same as the doughnut chart.

We can change the border alignment with the borderAlign property.

If it’s 'center' , then the border of the arcs will overlap.

If it’s 'inner' , then it’s guaranteed that the borders won’t overlap.

We can change the polar area chart’s global default options with the Chart.defaults.polarArea property.

The full list of options are at https://www.chartjs.org/docs/latest/charts/polar.html.

Bubble Chart

A bubble chart is used to display 3 dimensions of data at the same time.

The location of the bubble is determined by the first 2 dimensions and the corresponding x and y axes.

For example, we can write:

var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'bubble',
  data: {
    datasets: [{
        label: 'John',
        data: [{
          x: 3,
          y: 7,
          r: 10
        }],
        backgroundColor: "green",
        hoverBackgroundColor: "green"
      },
      {
        label: 'Paul',
        data: [{
          x: 6,
          y: 2,
          r: 10
        }],
        backgroundColor: "green",
        hoverBackgroundColor: "green"
      },
      {
        label: 'George',
        data: [{
          x: 2,
          y: 6,
          r: 10
        }],
        backgroundColor: "green",
        hoverBackgroundColor: "green"
      },
    ]
  }
});

We have an array with the datasets property.

Each entry has the data property with an object with the x , y and r properties.

x and y are the x coordinates.

And r is the radius of the bubble in pixels.

r isn’t scaled by the chart. It’s the eaw radius in pixels of the bubble drawn in the canvas.

We can change many other options like the border, background, hover background color, hover radius, label, and more.

The full list of options are at https://www.chartjs.org/docs/latest/charts/bubble.html

Conclusion

We can create doughnut, pie, polar area, and bubble charts with Chart.js

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Singletons and Decorators

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at some basic design patterns.

Class-Like Singleton

We can create a singleton object by storing the class instance in a global object.

For instance, we can write:

function Foo() {
  if (typeof globalFoo === "undefined") {
    globalFoo = this;
  }
  return globalFoo;
}

then we can create a Foo instance by writing:

const a = new Foo();
const b = new Foo();
console.log(a === b);

And the console log should log true since we store the existing instance in a global variable.

Then we returned it if it’s not undefined .

Singleton Stored in the Property of the Constructor

We know we shouldn’t use global variables, so we can store the singleton instance as a property of the constructor instead.

Functions can have properties since they are objects.

So we can write:

function Foo() {
  if (typeof Foo.instance === "undefined") {
    Foo.instance = this;
  }
  return Foo.instance;
}

The only change is that we store the property in the instance instead of in a global variable.

We can also store it in a private property if we put it in a function.

So we can write:

const Foo = (() => {
  let instance;
  return function() {
    if (typeof instance === "undefined") {
      instance = this;
    }
    return instance;
  }
})();

and do the same thing.

This way, we can’t accidentally change the instance to something else.

Factory Pattern

The factory pattern is creational design pattern.

It deals with creating objects.

The factory is a function that can help us create similar types of objects with one function.

For instance, we can create a function by writing:

const createElement = (type, url) => {
  if (type === 'Image') {
    return new Image(url);
  }
  if (type === 'Link') {
    return new Link(url);
  }
  if (type === 'Text') {
    return new Text(url);
  }
}

We return the constructor instance based on the type value.

And we also take the url that’s used with the constructors.

Decorator Pattern

The decorator pattern is a structural pattern.

We can use this pattern to extend the functionality of objects.

With this pattern, we can extend an object’s functionality by picking the decorators that we want to apply to the object.

For instance, we can write:

function Person(name) {
  this.name = name;
  this.say = function() {
    console.log(this.name);
  };
}

function DecoratedPerson(person, street, city) {
  this.person = person;
  this.person = person.name;
  this.street = street;
  this.city = city;
  this.say = function() {
    console.log(this.name, this.street, this.city);
  };
}

We have 2 constructors the Person and DecoratedPerson classes.

Person is the class that we use as the base for the DecoratedPerson class.

The DecoratedPerson class adds extra properties on top of the Person class.

This way, we keep the interface of DecoratedPerson the same as the Person constructor for the ones that come from Person .

But we add more properties exclusive to the DecoratedPerson class.

Conclusion

We can create singleton objects with a class like syntax.

The decorator pattern lets us extend the functionality of constructors.

Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Private Entities and Chaining

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at some basic coding and design patterns.

Privileged Methods

Privilege methods is a term coined by Douglas Crockford.

These are public methods that can access private methods and properties.

They act as a bridge to make some private functionality available in a controlled manner.

For instance, we can write:

let APP = {};
APP.dom = (() => {
  const setStyle = function(el, prop, value) {
    console.log('setStyle');
  };

  const getStyle = function(el, prop) {
    console.log('getStyle');
  };

  return {
    setStyle,
    getStyle,
    //...
  };
}());

We have the setStyle and getStyle functions that are defined in the IIFE.

We expose them by return the object and then assigning it to a property that’s available outside the function.

These functions can have private variables inside them so that we can do whatever we want without exposing everything.

Immediate Functions

Immediate functions let us keep global namespace clean by wrapping our code in an anonymous function and run them immediately.

For instance, we can write:

(function() {
  // ...
}());

to create a function and call it immediately.

This way, we can keep private variables and methods inside it.

For example, we can write:

let APP = {};
APP.methods = (() => {
  function _private() {
    // ...
  }
  return {
    foo() {
      console.log('...');
      _private();
    },
    bar() {
      console.log('...');
    }
  };
}());

We have the IIFE, which returns an object with the foo method that calls the private _private function.

Modules

ES5 doesn’t have modules, so we may have to use modules for scripts if we’re writing scripts for the browser.

For instance, we can create a module by writing:

let APP = {
  module: {}
};
APP.module.foo = (() => {
  const another = APP.module.another;
  let foo, bar;

  function hidden() {}
  //...

  return {
    hi() {
      return "hello";
    }
  };
}());

We created a foo module which references an another module.

In the module, we defined some variables and the hidden function.

And we return a public hi method in an object.

Then we can hi by writing:

APP.module.foo.hi()

Chaining

Chaining is a pattern that lets us call multiple methods in one line.

The methods are linked to a chain.

For instance, we can write:

class Foo {
  foo() {
    this.foo = 'foo';
    return this;
  }

  bar() {
    this.bar = 'bar';
    return this;
  }

  baz() {
    this.baz = 'baz';
    return this;
  }
}

We have multiple methods that return this , which is the Foo instance.

This way, we can call the methods in a chain.

So we can write:

new Foo().foo().bar().baz();

to call the chain of methods.

Conclusion

We can have private variables, objects, and functions that are inside a function.

Also, we can create our own modules with our own objects.

And we can make them chainable by returning this in a method.