Display multiple datasets from array with chart.js - javascript

I'm trying to display a multiple line chart of about the growth of the population on the different department of a country but when I get the JSON from PHP I can't iterate the array for getting the year and total of the population. Here's my code:
$(document).ready(function(){
$.ajax({
url: "../assets/api/stats.php",
data: "stat=birth&in=departement",
type: "GET",
success: function(data) {
console.log(data);
var departement = {
Zone: []
};
var year = {
Birth: []
};
var total = {
Birth: []
};
var len = data.length;
console.log(data.length);
var lctx = $('#line-chart- departement');
for (var j = 0; j < len; j++) {
departement.Zone.push(data[j][0].departement);
for (var i = 0; i < data.length; i++) {
annee.Naissance.push(departement.Zone[i].annee);
total.Naissance.push(departement.Zone[i].total);
}
var data = {
labels: annee.Naissance,
datasets: [{
label: data[j],
data: total.Naissance,
backgroundColor: getRandomColor(),
borderColor: "#3e95cd",
fill: false,
lineTension: 0,
pointRadiues: 5
}]
};
console.log();
var chart = new Chart(lctx, {
type: "line",
data: data,
options: {}
});
}
},error: function(data) {
//console.log(data)
}
});
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;}
});
And there is my array
[
{
"Nord-Est":
[
{
"annee": "1995",
"totalnaissance": "1"
}
]
},
{
"Ouest":
[
{
"annee": "1994",
"totalnaissance": "2"
},
{
"annee": "1995",
"totalnaissance": "1"
}
]
},
{
"Nippes":
[
{
"annee": "1951",
"totalnaissance": "1"
},
{
"annee": "1987",
"totalnaissance": "1"
},
{
"annee": "1986",
"totalnaissance": "1"
},
{
"annee": "1992",
"totalnaissance": "2"
}
]
},
{
"Sud-Est":
[
{
"annee": "1985",
"totalnaissance": "1"
}
]
}
]

That turned out to be 'more than meets the eye'.
Since we need all the years as x axis, we need to go through the data twice - once to get all the years, once to get the data for each year. If data is not available for that year, we have to enter null. Otherwise the x and y points get mismatched.
After all the years are fetched, they have to be sorted in ascending order, and we need to get the totalnaissance data in the same order.
You had given the borderColor a fixed value of #3e95cd, but for a line chart a border color IS the line color. So I've changed that. I've also made the backgroundColor 'transparent' and pointBackgroundColor equal to borderColor.
I've created a Pen.
<canvas id="myChart" width="500" height="500"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var data = {
Nippes: [
{
annee: "1951",
totalnaissance: "1"
},
{
annee: "1986",
totalnaissance: "1"
},
{
annee: "1987",
totalnaissance: "1"
},
{
annee: "1992",
totalnaissance: "2"
}
],
"Nord-Est": [
{
annee: "1995",
totalnaissance: "1"
}
],
Ouest: [
{
annee: "1994",
totalnaissance: "2"
},
{
annee: "1995",
totalnaissance: "1"
}
],
"Sud-Est": [
{
annee: "1985",
totalnaissance: "1"
}
]
};
var departments = [];
var annees = [];
for (var department in data) {
if (data.hasOwnProperty(department)) {
var departmentData = data[department];
getYears(departmentData);
}
}
annees.sort();
for (var department in data) {
if (data.hasOwnProperty(department)) {
var departmentData = data[department];//getDataForDepartment(i);
var totalnaissanceData = getTotalNaissanceDataForDep(departmentData);
var departmentObject = prepareDepartmentDetails(department, totalnaissanceData);
departments.push(departmentObject);
}
}
var chartData = {
labels: annees,
datasets : departments
};
var chart = new Chart(ctx, {
type: "line",
data: chartData,
options: {}
});
function getDataForDepartment(index){
return data[i][Object.keys(data[i])[0]];
}
function getYears(departmentData){
for (var j = 0; j< departmentData.length; j++){
if (!annees.includes(departmentData[j].annee)){
annees.push(departmentData[j].annee);
}
}
}
function getTotalNaissanceDataForDep(departmentData){
var totalnaissanceData = [];
for (var j = 0; j < annees.length; j++){
var currentAnnee = annees[j];
var currentTotalNaissance = null;
for (var k = 0; k< departmentData.length; k++){
if (departmentData[k].annee === currentAnnee){
currentTotalNaissance = departmentData[k].totalnaissance;
break;
}
}
totalnaissanceData.push(currentTotalNaissance);
}
return totalnaissanceData;
}
function prepareDepartmentDetails(departmentName, totalnaissanceData){
var dataColor = getRandomColor();
return {
label : departmentName,
data : totalnaissanceData,
backgroundColor: 'transparent',
borderColor: dataColor,//"#3e95cd",
pointBackgroundColor : dataColor,
fill: false,
lineTension: 0,
pointRadius: 5
}
}
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
</script>

Related

change data in nested array

I am trying to use an javascript algorithm to convert the data from products mode to reward mode, please help me :
var products = [{
id: "65864",name_fa:"پک دفتر 40 برگ وزيري شوميز کلاسيک 40 ",
details:[{master: 5,slave: 0,slave2: 0},{master: 11,slave: 0,slave2: 0}]
},{
id: 67532,name_fa: "100-بازی لونا",
details:[{master: 0,slave: 5,slave2: 0}]
}]
TO :
reward: [
{products: [
{
id: "65864",
name_fa:"پک دفتر 40 برگ وزيري شوميز کلاسيک 40" ,
"master": "5",
"slave": "0",
"slave2": "0"
},
{
"id": "67532",
"name_fa":"100-بازی لونا" ,
"master": "0",
"slave": "5",
"slave2": "0"
}
],
},
{"products": [
{
"id": "65864",
"name_fa":"پک دفتر 40 برگ وزيري شوميز کلاسيک 40" ,
"master": "11",
"slave": "0",
"slave2": "0"
},
{
"id": "67532",
"name_fa":"100-بازی لونا" ,
"master": "0",
"slave": "5",
"slave2": "0"
}
],
}
]
example:
[1,2],[3]
to
[1,3],[2,3]
I am trying to use an javascript algorithm to convert the data from products mode to reward mode, please help me
It's called cartesian product. I'm reusing a function and apply it on 2 arrays. The products, and the details. Then I combine those arrays (should be same length) into the required result.
// from: https://stackoverflow.com/a/36234242/3807365
function cartesianProduct(arr) {
return arr.reduce(function(a, b) {
return a.map(function(x) {
return b.map(function(y) {
return x.concat([y]);
})
}).reduce(function(a, b) {
return a.concat(b)
}, [])
}, [
[]
])
}
var products = [{
id: "65864",
name_fa: "پک دفتر 40 برگ وزيري شوميز کلاسيک 40 ",
details: [{
master: 5,
slave: 0,
slave2: 0
}, {
master: 11,
slave: 0,
slave2: 0
}]
}, {
id: 67532,
name_fa: "100-بازی لونا",
details: [{
master: 0,
slave: 5,
slave2: 0
}]
}];
var input = products.reduce(function(agg, item) {
agg.push(item.details);
return agg;
}, []);
var a = cartesianProduct(input);
// same for the id and names
var input2 = products.reduce(function(agg, item) {
var ids = []
item.details.forEach(function(_) {
ids.push({
id: item.id,
name_fa: item.name_fa
})
})
agg.push(ids);
return agg;
}, []);
var b = cartesianProduct(input2);
//console.log(JSON.stringify(a, null, 2));
//console.log(b)
var reward = [];
for (var i = 0; i < a.length; i++) {
var newGroup = {
products: []
}
for (var j = 0; j < a[i].length; j++) {
var newMan = {}
newGroup.products.push({
...b[i][j],
...a[i][j]
})
}
reward.push(newGroup)
}
console.log(reward)
.as-console-wrapper {
max-height: 100% !important
}

How can I add a border to the columns on this graph.js

I've put together a graph which pulls data from google.
I'm trying to change the styling but can't find a way to do it through CSS. I want to add a border to both columns.
I couldunt add all the code, but I can see this is the part that mentions colors.
https://codepen.io/jameswill77/pen/WNzXxeJ
const colors = ['#FDF7F2', '#23F0C7'];
dataj = JSON.parse(data.toJSON());
console.log(dataj.cols[0].label);
const labels = [];
for (c = 1; c < dataj.cols.length; c++) {
if (dataj.cols[c].label != "") {
labels.push(dataj.cols[c].label);
}
}
console.log(labels);
const datasets = [];
for (i = 0; i < dataj.rows.length; i++) {
const series_data = [];
for (j = 1; j < dataj.rows[i].c.length; j++) {
if (dataj.rows[i].c[j] != null) {
if (dataj.rows[i].c[j].v != null) {
series_data.push(dataj.rows[i].c[j].v);
} else {
series_data.push(0);
}
}
}
var dataset = {
label: dataj.rows[i].c[0].v,
backgroundColor: colors[i],
borderColor: colors[i],
data: series_data
}
datasets.push(dataset);
}
console.log(datasets);
const chartdata = {
labels: labels,
datasets: datasets
};
var canvas = document.getElementById("myChart");
var setup = {
type: 'bar',
data: chartdata,
options: {
plugins: {
title: {
display: true,
text: dataj.cols[0].label
}
},
responsive: true,
}
}
chart = new Chart(canvas, setup);
}
added option borderWidth and changed value of borderColor in the datasets.
https://codepen.io/fver1004/pen/MWVOJpR?editors=1010
google.charts.load('current', {
'packages': ['corechart', 'bar']
});
google.charts.setOnLoadCallback(initChart);;
function initChart() {
URL = "https://docs.google.com/spreadsheets/d/1MV4chXniMBHj1ROAIf-BZR3LsoN-HT180pUwivU5Jbc/edit#gid=2112195720";
var query = new google.visualization.Query(URL);
query.setQuery('select *');
query.send(function(response) {
handleQueryResponse(response);
});
}
function handleQueryResponse(response) {
var data = response.getDataTable();
var columns = data.getNumberOfColumns();
var rows = data.getNumberOfRows();
// console.log(data.toJSON());
const colors = ['#eeeeee', '#23F0C7'];
const border_colors = ['#ececec', '#21DEC5'];
dataj = JSON.parse(data.toJSON());
// console.log(dataj.cols[0].label);
const labels = [];
for (c = 1; c < dataj.cols.length; c++) {
if (dataj.cols[c].label != "") {
labels.push(dataj.cols[c].label);
}
}
// console.log(labels);
const datasets = [];
for (i = 0; i < dataj.rows.length; i++) {
const series_data = [];
for (j = 1; j < dataj.rows[i].c.length; j++) {
if (dataj.rows[i].c[j] != null) {
if (dataj.rows[i].c[j].v != null) {
series_data.push(dataj.rows[i].c[j].v);
} else {
series_data.push(0);
}
}
}
var dataset = {
label: dataj.rows[i].c[0].v,
backgroundColor: colors[i],
borderColor: border_colors[i],
borderWidth: 4,
data: series_data
}
datasets.push(dataset);
}
console.log(datasets);
const chartdata = {
labels: labels,
datasets: datasets
};
var canvas = document.getElementById("myChart");
var setup = {
type: 'bar',
data: chartdata,
options: {
plugins: {
title: {
display: true,
text: dataj.cols[0].label
}
},
responsive: true,
}
}
chart = new Chart(canvas, setup);
}

How do I add and manipulate the values inside my pie chart?

I'm using http://d3pie.org/ to generate a pie chart for my web application. Now, I want to manipulate the value appearing on my chart. Currently, the values appearing have more than 4 decimals. For example, 10.35234234234 . I just want 10.3523 to appear.
Here's my current code:
function drawPie(id,from,to,C,formula){
var subArray = getSubArray(C.table,from,to);
if(Object.keys(subArray).length){
var partials = createPartials(subArray, C.attributes);
//console.log("partials -> ",partials);
formula = formula.slice(1,-1);
//console.log("formula ->" , formula);
formula = formula.split(",");
//console.log("formula ->" , formula);
var cloneFormula = formula.slice();
for( var i in partials){
if(i.substr(0,1) == "$"){
for(var j = 0; j< formula.length; j++){
formula[j] = replaceFunction(i,formula[j],partials[i]);
}
}
}
//console.log("replaced formula ->" , formula);
var data = [];
var isEmpty = true;
for(var j = 0; j< formula.length; j++){
var label = cloneFormula[j].split(/(?=[-+*\/])/)[0].split(".")[1];
var temp = {};
try{
temp.value = eval(formula[j]);
}catch(err){
temp.value = 0;
}
temp.label = partials[label + ".name"];
temp.color = partials[label + ".color"];
data.push(temp);
if(temp.value != 0){
isEmpty = false;
}
}
if(isEmpty){
return true;
}
//console.log("data ->" , data);
var pie = new d3pie(id, {
"size": {
"canvasHeight": 400,
"canvasWidth": 800, //see defect 1418
"pieOuterRadius": "88%"
},
"data": {
"content": data
},
"labels": {
"outer": {
"pieDistance": 100
},
"inner": {
"format": "value"
},
"mainLabel": {
"font": "verdana"
},
"percentage": {
"color": "#e1e1e1",
"font": "verdana",
"decimalPlaces": 0
},
"value": {
"color": "#e1e1e1",
"font": "verdana"
},
"lines": {
"enabled": true,
"color": "#cccccc"
},
"truncation": {
"enabled": true
}
},
"effects": {
"pullOutSegmentOnClick": {
"effect": "linear",
"speed": 400,
"size": 8
}
}
});
return false;
}
return true;
}
Can you help me try to modify the texts appearing inside my pie chart?
use the following to strip the number and then round it.
function strip(number) {
return (parseFloat(number).toPrecision(4));
}
example
var number = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
function strip(number) {
return (parseFloat(number).toPrecision(6));
}
window.alert(strip(number));
For the generator you are using, go to the labels section, and under the label styles / Settings you will find the option for decimal places for percentage values. Enter the number of decimal places you would like to limit the labels to.

How do I use a function inside another function's function

I am trying to capitalize the first letter of each word in the other function.
This is the function to turn each words first letter to capital that I am using.
function capital_letter(str)
{
str = str.split(" ");
for (var i = 0, x = str.length; i < x; i++) {
str[i] = str[i][0].toUpperCase() + str[i].substr(1);
}
return str.join(" ");
}
Here’s the second function that I’m trying to use the first one in, but it is not working.
$(document).ready(function() {
$('#list').dataTable({
"ajax":{
url :"list.php",
type: "GET",
error: function(){
$("#post_list_processing").css("display","none");
}
},
"columns": [
{ "data": function capital_letter(item) {
return item.title;
}
},
{ "data": "description" },
{ "data": "time" }
]
});
});
You should only call the function like the following:
$(document).ready(function() {
$('#list').dataTable({
ajax: {
url: 'list.php',
type: 'GET',
error: function() {
$('#post_list_processing').css('display', 'none');
},
},
columns: [{
data: capital_letter(item.title);
},
{ data: 'description' },
{ data: 'time' },
],
});
});
You're redefining the function instead of actually using it... Call it like this;
...
"columns": [
{ "data": capital_letter(item.title) }
...
You are not calling the function correctly. Change the following in your code.
"columns": [
{ "data": capital_letter(item.title) }
Created a working snippet.
function capital_letter(str) {
str = str.split(" ");
for (var i = 0, x = str.length; i < x; i++) {
str[i] = str[i][0].toUpperCase() + str[i].substr(1);
}
return str.join(" ");
}
const columns = [{
"data": capital_letter("abc")
},
{
"data": "description"
},
{
"data": "time"
}
]
console.log(columns)

How do I change the colors on Y-Axis for values above, below zero? Chart.js 2.6

Using chart.js 2.6 Is there a way to dynamically change the bars in my chart for values above zero and below zero? The graph series data is being generated via a call to a method. Right now its just a random number generator but will be a DB call.
function changeWOWData(chart) {
var datasets = chart.data.datasets;
var labelLen = chart.data.labels.length;
if (datasets[0]) {
for (i = 0, len = datasets.length; i < len; i++) {
try {
for (j = 0, len = labelLen; j < len; j++) {
datasets[i].data[j] = getRandomInt(-100, 100);
}
} catch (e) {
console.log(e.message);
}
}
}
}
Chart looks like this:
I want the chart bars above zero to be blue, the bars below zero to be red.
Any/all replies appreciated. Thanks in advance!
Griff
** Edit ** Added the code from the answer below as such:
var myBarChart = new Chart(wowChart, {
type: 'bar',
data: wowData,
plugins: [{
beforeDraw: function (c) {
var data = c.data.datasets[0].data;
for (var i in data) {
try {
var bar = c.data.datasets[0]._meta[0].data[i]._model;
if (data[i] > 0) {
bar.backgroundColor = '#07C';
} else bar.backgroundColor = '#E82020';
} catch (ex) {
console.log(ex.message);
}
console.log(data[i]);
}
}
}],
options: wowOptions
});
Every other line of the console I see the data element along with the exception
You could accomplish that using the following chart plugin :
plugins: [{
beforeDraw: function(c) {
var data = c.data.datasets[0].data;
for (let i in data) {
let bar = c.data.datasets[0]._meta['0'].data[i]._model;
if (data[i] > 0) {
bar.backgroundColor = '#07C';
} else bar.backgroundColor = '#E82020';
}
}
}]
add this followed by your chart options
ᴅᴇᴍᴏ
var ctx = document.getElementById("canvas").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'LEGEND',
data: [9, 14, -4, 15, -8, 10]
}]
},
options: {},
plugins: [{
beforeDraw: function(c) {
var data = c.data.datasets[0].data;
for (let i in data) {
let bar = c.data.datasets[0]._meta['0'].data[i]._model;
if (data[i] > 0) {
bar.backgroundColor = '#07C';
} else bar.backgroundColor = '#E82020';
}
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas" height="180"></canvas>
in chartjs v3 you can use Simply scriptable option
example:
datasets: [
{
data: this.chartData,
backgroundColor(context) {
const index = context.dataIndex
const value = context.dataset.data[index]
return value < 0 ? 'red' : 'blue'
}
}
]
visit https://www.chartjs.org/docs/latest/general/options.html#scriptable-options

Categories