chart.js display a default chart with option value - javascript

so I'm generating charts with a database and displaying them with JSON script and it works fine but the chart only displays when I click an option value, what I'm trying to do now is set a default value option for when the website opens it displays a default chart if that makes sense, below is my chart.js code.
function renderHtmlChart(){
$(document).ready(function (){
var selection= document.getElementById('YEAR').value;
var link = "https://udon.ads.ntu.ac.uk/web/itec30151/N0773065/new/data.php?YEAR='"+selection+"'";
$.ajax({
url: link,
method: "GET",
success: function(data=this.responseText) {
console.log(data);
var Destination = [];
var Bookings = [];
for(var i in data) {
Destination.push(data[i].Destination);
Bookings.push(data[i].Bookings);
}
createChart(Destination,Bookings,selection)
},
error: function(data) {
console.log(data);
}
});
});
}
function createChart(Destination,Bookings,selection){
var universalOptions = {
maintainAspectRatio: true,
responsive: false,
title: {
display: true,
text: 'Top 5 Flight Bookings'
},
legend: {
display: true,
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
},
scaleLabel: {
display: true,
labelString: 'Bookings'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Destinations'
}
}],
}
}
var chartdata = {
labels: Destination,
datasets : [
{
label: selection,
data: Bookings,
backgroundColor: ["#3366cc","#dc3912","#ff9900","#109618","#990099"],
borderWidth: '1',
borderColour: 'grey',
hoverBorderColor: 'black',
fill: false,
pointRadius: 0,
}
]
};
//stop overlap
$('select').on('change',function(){
barGraph.destroy();
});
// this makes legend hidden
var update_caption = function(legend) {
labels[legend.text] = legend.hidden;
var selected = Object.keys(labels).filter(function(key) {
return labels[key];
});
};
//this creates new graph
var ctx = document.getElementById('myChart');
var barGraph = new Chart(ctx, {
type: 'bar',
data: chartdata,
options: universalOptions,
responsive: false,
});
}

hope you have latest version of jquery like:-
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
hope this will help
//create renderHtmlChart function
function renderHtmlChart()
{
var selection= document.getElementById('YEAR').value;
var link = "https://udon.ads.ntu.ac.uk/web/itec30151/N0773065/new/data.php?YEAR='"+selection+"'";
$.ajax({
url: link,
method: "GET",
success: function(data=this.responseText)
{
console.log(data);
var Destination = [];
var Bookings = [];
for(var i in data)
{
Destination.push(data[i].Destination);
Bookings.push(data[i].Bookings);
}
createChart(Destination,Bookings,selection)
},
error: function(data)
{
console.log(data);
}
});
}
//create createChart function
function createChart(Destination,Bookings,selection)
{
var universalOptions =
{
maintainAspectRatio: true,
responsive: false,
title:
{
display: true,
text: 'Top 5 Flight Bookings'
},
legend:
{
display: true,
},
scales:
{
yAxes: [{
ticks: {
beginAtZero: true,
},
scaleLabel: {
display: true,
labelString: 'Bookings'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Destinations'
}
}],
}
}
var chartdata = {
labels: Destination,
datasets : [
{
label: selection,
data: Bookings,
backgroundColor: ["#3366cc","#dc3912","#ff9900","#109618","#990099"],
borderWidth: '1',
borderColour: 'grey',
hoverBorderColor: 'black',
fill: false,
pointRadius: 0,
}
]
};
// this makes legend hidden
var update_caption = function(legend) {
labels[legend.text] = legend.hidden;
var selected = Object.keys(labels).filter(function(key) {
return labels[key];
});
};
//this creates new graph
var ctx = document.getElementById('myChart');
var barGraph = new Chart(ctx, {
type: 'bar',
data: chartdata,
options: universalOptions,
responsive: false,
});
}
$(funtion(){
//onload call renderHtmlChart function
renderHtmlChart();
//on select input change call renderHtmlChart function
$('select').on('change',function(){
renderHtmlChart();
});
})

Related

Chart.js StackedBar doesn't show labels on bar and maximum y-value

I saw this other post on Stackoverflow and it is what I want to do. I have my awesome graph in my ASP.NET Core web application by Chart.js#2.9.4. I read the data from an API.
As I read, I added chartjs-plugin-datalabels on my project and add the script to the page.
$.ajax({
url: 'myapi',
dataType: 'json'
})
.fail(function (err) {
alert(err);
})
.done(function (data) {
$("#chart").html('');
$("#chart").html('<canvas id="barChart" style="min-height: 300px; height: 3000px; max-height: 300px; max-width: 100%;"></canvas>');
var stackedBarChartCanvas = $('#barChart').get(0).getContext('2d')
var stackedBarChartData = $.extend(true, {}, data)
var temp0 = data.datasets[0]
var temp1 = data.datasets[1]
stackedBarChartData.datasets[0] = temp1
stackedBarChartData.datasets[1] = temp0
var stackedBarChartOptions = {
responsive: true,
maintainAspectRatio: false,
tooltips: {
mode: 'label',
callbacks: {
label: function (tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " + numberWithCommas(tooltipItem.yLabel);
}
}
},
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true,
max: 100,
ticks: {
callback: function (value) {
return numberWithCommas(value);
},
},
}]
},
plugins: {
datalabels: {
display: true,
align: 'center',
anchor: 'center',
display: function (context) {
return context.dataset.data[context.dataIndex] > 15;
},
font: {
weight: 'bold'
},
formatter: Math.round
}
}
}
var stackedBarChart = new Chart(stackedBarChartCanvas, {
type: 'bar',
data: stackedBarChartData,
options: stackedBarChartOptions,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
ctx.fillText(bar.value, bar.x, bar.y - 5);
});
})
}
})
})
If I move the mouse over the graph, nothing happens but in the Console I have this error
Uncaught TypeError: Cannot read property 'r' of null (Chart.js:1655)
Also, I want to fix the maximum value in the y-axis must be 100 because there are only percentage. Although, I set the y-axis to 100, the chart displays 120.
Chart.js doesn't show the data because it is required to set some parameters:
HoverBackgroundColor
HoverBorderWidth
HoverBorderColor
After settings them, the chart is working.

Display chartjs bar chart with dynamic data

I need to display a bar chart that I must make with chartJs with dynamic data, I get these dynamic data from an xml link.
I work with two datafields: TaskName and TaskPercentCompleted
The final result must be something like this:
https://scontent.ftun3-1.fna.fbcdn.net/v/t1.15752-9/67290623_1101713790034749_6213821876259520512_n.png?_nc_cat=107&_nc_oc=AQkVef74ok1IcC0m0ujX4t7c4EhNAEs0C-lejsBTHCj9U2zrFRo2UA_gWnuOeA4ZJco&_nc_ht=scontent.ftun3-1.fna&oh=e8503be685f36c7440362b5a0d3c85f5&oe=5DA3B54E
And this is a part of the xml link:
https://scontent.ftun3-1.fna.fbcdn.net/v/t1.15752-9/66803472_2156647134463530_3324310068698021888_n.png?_nc_cat=100&_nc_oc=AQmuJ-gA1lT7F-whtw329vy_eciZoCWNn5hxCW2Zdp4X_RBfyZknVR1Bza-UF_nDn7s&_nc_ht=scontent.ftun3-1.fna&oh=d6ced2436a0c666be4dfd4fe5138a72f&oe=5DAADE21
I got a code but it doesn't work the way I want, it's regrouping data and I don't want that.
window.addEventListener('load',function() {
var dataURL = _spPageContextInfo.webAbsoluteUrl + "/_api/ProjectData/[en-US]/Tasks?$select=TaskName,TaskPercentCompleted&$filter=ProjectName%20eq%20%27Bay%20Plaza%27%20and%20TaskIsSummary%20eq%20true%20and%20TaskIsProjectSummary%20eq%20false";
$.ajax({
url: dataURL,
method: "GET",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
var dataResults = data.d.results;
var itermeidiaryObject = {};
$.each(dataResults, function(key, value) {
var nomTask = value.TaskName;
var epn = value.TaskPercentCompleted;
if (epn != null) {
itermeidiaryObject[epn] = ++itermeidiaryObject[epn] || 1;
}
});
var finalObject = Object.keys(itermeidiaryObject).map(function(key) {
return {
label: itermeidiaryObject[key],
y: key
}
});
var pievalues = finalObject.map(function(value, index) {
return value.y;
});
var labels = finalObject.map(function(value, index) {
return value.label;
});
var colorscheme = colors.slice(0, labels.length);
var ctx = document.getElementById('myChart2').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
data: pievalues,
backgroundColor: colorscheme
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
beginAtZero: true // Edit the value according to what you need
}
}],
yAxes: [{
stacked: true
}]
},
title: {
display: true,
position: "top",
text: "Nombre de projets par direction",
fontSize: 18,
fontColor: "#111"
},
legend: {
display: false
}
}
});
}
});
});
var colors = ["#0074D9", "#FF4136", "#2ECC40", "#FF851B", "#7FDBFF", "#B10DC9", "#FFDC00", "#001f3f", "#39CCCC", "#01FF70", "#85144b", "#F012BE", "#3D9970", "#111111", "#AAAAAA"];
I solved the problem
window.addEventListener('load',function() {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/ProjectData/[en-US]/Tasks?$select=TaskName,TaskPercentCompleted&$filter=ProjectName%20eq%20%27Bay%20Plaza%27%20and%20TaskIsSummary%20eq%20true%20and%20TaskIsProjectSummary%20eq%20false",
method: "GET",
headers: { "Accept": "application/json; odata=nometadata" },
success: function (data) {
if (data.value.length > 0) {
var pieValues = [];
var pieLabels = [];
for (var i = 0; i < data.value.length; i++) {
pieValues.push(parseInt(data.value[i].TaskPercentCompleted));
pieLabels.push(data.value[i].TaskName);
}
var pieData = {
datasets: [{
data: pieValues,
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850",
"#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850",
"#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850",
"#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850",
"#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850",
"#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850","#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
}],
labels: pieLabels
};
var ctx = document.getElementById("myChart2");
var myPieChart = new Chart(ctx, {
//type: 'pie',
type: 'bar',
data: pieData,
options: {
responsive: true,
legend: { display: false },
title: {
display: true,
text: 'Nom de tâche par pourcentage'
},
scales: {
xAxes: [{
ticks: {
maxRotation: 90,
minRotation: 90,
display: false
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
},
error: function (data) {
//
}
});
});

How to display different tooltip based on data values in ChartJS v2?

I’m using ChartJs, to display a Line chart and I’m trying to do 2 things :
The first one is to display different colors based on the tooltip’s value. Highest value vs Medium value
The second one is to display a different tooltip if the tooltips value is the lowest. Minimun value
I’ve tried to use a custom plugins to do this, but It didn’t work
This is the code I've managed to do so far :
Chart.plugins.register({
beforeRender: function(chart) {
if (chart.config.options.showAllTooltips) {
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function(dataset, i) {
chart.getDatasetMeta(i).data.forEach(function(sector, j) {
console.log(j, sector);
chart.pluginTooltips.push(
new Chart.Tooltip(
{
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector],
},
chart
)
);
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function(chart, easing) {
if (chart.config.options.showAllTooltips) {
if (!chart.allTooltipsOnce) {
if (easing !== 1) return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function(tooltip) {
tooltip.initialize();
tooltip._options.bodyFontFamily = "Visby";
// Change color based on value
tooltip._options.bodyFontColor = '#FEB122';
// Change tooltip's html if minimun value of dataset
// Values .datapoints[0].value
// console.log(tooltip._model);
tooltip._options.displayColors = false;
tooltip._options.bodyFontSize = tooltip._chart.height * 0.05;
tooltip._options.yPadding = 0;
tooltip._options.xPadding = 0;
tooltip.update();
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
});
let canvas = document.getElementById("myLineChart");
Chart.defaults.global.defaultFontFamily = "Visby";
const ctx = canvas.getContext('2d');
const labels = JSON.parse(ctx.canvas.dataset.dates);
const prices = JSON.parse(ctx.canvas.dataset.prices);
const myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: "Prix du billet",
data: prices,
backgroundColor: [
'rgba(0, 0, 0, 0)',
],
borderColor: [
'#F2F2F2',
],
pointBackgroundColor:
'#FEB122',
pointBorderColor:
'#FEB122',
borderWidth: 3,
}]
},
options: {
showAllTooltips: true, // call plugin we created
responsive: true,
cutoutPercentage: 60,
legend: {
position: "bottom"
},
animation: {
animateScale: true,
animateRotate: true
},
tooltips: {
enabled: false,
backgroundColor:"rgba(0,0,0,0)",
callbacks: {
title: function(tooltipItems, data) {
return "";
},
label: function(tooltipItem, data) {
var datasetLabel = "";
var label = data.labels[tooltipItem.index];
return data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] + '€';
},
labelColor: function(tooltipItem, data) {
// console.log(data);
}
}
},
legend: {
display: false
},
layout: {
padding: {
left: 32,
right: 32,
top: 32,
bottom: 32
}
},
scales: {
xAxes: [{
gridLines: {
display: false,
drawBorder: false,
},
}],
yAxes: [{
display: false
}]
}
}
});
How could I make this work ?
I've managed to do that by using the plugin Chartjs Datalabels.
And using the scriptable colors options.

Chartjs X axis labels will not display

The documentation for time in ChartJs is extremely vague and gives little working examples so I'm struggling to get a time series working for temperature data recorded at a particular time. I can get the correct time format to appear in the tooltip, but it will not appear on the X axis.
Graph code:
<script>
var ctx = document.getElementById('myChart');
var data = {
labels: [],
datasets: [{
label: "Temperature Graph",
fill: false,
borderColor: '#3cba9f',
data: []
}]
}
const options = {
type: 'line',
data: data,
options: {
fill: false,
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day',
stepSize: 1,
displayFormats: {
day: 'MMM D'
}
},
display: true,
scaleLabel: {
display: true,
labelString: "Date",
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
},
display: true,
scaleLabel: {
display: true,
labelString: "Temperature",
}
}]
}
}
}
var chart = new Chart(ctx, options)
</script>
Data collection code:
window.onload = function load() {
getData();
}
var prevData = [];
var prevLabels = [];
function getData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI('http://localhostlocalhost/getTemp'));
xhr.onload = function() {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
console.log(data);
var label = data.timestamp * 1000;
prevData.push(data.temperature);
prevLabels.push(label);
chart.data.datasets[0].data = prevData;
chart.data.labels = prevLabels;
chart.update();
}
else {
alert(xhr.status);
}
};
xhr.send();
setTimeout(getData, 10000);
}
Example xhr response:
{temperature: 17, humidity: 38, location: "location", timestamp: 1542824305}
The data is plotted to the graph and all works as expected, the time just does not appear on the X axis

JS import updated JSON file for use with ChartJS

I am trying to import and read from a JSON file that gets updated every few minutes by a different process. I need to loop through the values in this JSON files for use with ChartJS.org.
If I keep the JSON data local to the script in a var (var jsonfile={}) the chart works as expected.
What I am struggling to do is import the JSON file from outside the script (it is on the local web server under a different folder).
The JSON file looks exactly the same as data in the var below.
The below works as expected.
<div class="row">
<div class="col-4">
<div class="ca-comms-by-month">
</div>
<script>
var jsonfile = {
"comms_by_month": [
{
"name": "July",
"count": 2130
},
{
"name": "August",
"count": 890
},
{
"name": "September",
"count": 1654
},
{
"name": "October",
"count": 120
}
]
};
var labels = jsonfile.comms_by_month.map(function(e) {
return e.name;
});
var data = jsonfile.comms_by_month.map(function(e) {
return e.count;
});
function createConfig(details, data) {
return {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Comms count by month',
steppedLine: details.steppedLine,
data: data,
borderColor: details.color,
fill: true,
}]
},
options: {
responsive: true,
title: {
display: false,
text: details.label,
},
tooltips: {
enabled:true, // Disable this for custom tool tips || http://www.chartjs.org/docs/latest/configuration/tooltip.html
mode: 'index',
intersect: false,
cornerRadius:0
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Count'
},
ticks: {
beginAtZero:true
}
}]
},
legend: {
display: false, // False to hide the legdend dataset tile
labels: {
fontColor: 'rgb(255, 99, 132)'
}
}
}
};
}
window.onload = function()
{
var container = document.querySelector('.ca-comms-by-month');
var steppedLineSettings = [{
steppedLine:false,
label: '',
color: window.chartColors.purple
}];
steppedLineSettings.forEach(function(details) {
var div = document.createElement('div');
div.classList.add('chart-container');
var canvas = document.createElement('canvas');
div.appendChild(canvas);
container.appendChild(div);
var ctx = canvas.getContext('2d');
var config = createConfig(details, data);
new Chart(ctx, config);
});
};
</script>
</div>
</div>
The below code will display some of the data in the updated JSON file based on the getElementById names but this is no good to me as I need the ChartJS to go and get the values.
<h1 class="toolsportal text-right">Temp</h1>
<p id="demo"></p>
<p id="demo1"></p>
<br /><br /><br /><br />
<script>
var jsonurl = 'http://mydevicename/portal/js/export_json/dash-comms-month.json';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
var jsonfile = JSON.parse(this.responseText);
document.getElementById("demo").innerHTML = jsonfile.comms_by_month[0].month;
document.getElementById("demo1").innerHTML = jsonfile.comms_by_month[0].name;
}
};
xmlhttp.open("GET", jsonurl, true);
xmlhttp.send();
</script>
What I can't put together is how I can get the values out of the updated JSON file using the below functions that happily go and get the data from the local jsonfile{} var.
var labels = jsonfile.comms_by_month.map(function(e){return e.name;});
var data = jsonfile.comms_by_month.map(function(e){return e.count;});
I am clearly missing something fundamental, any pointers would be great.
Thanks
I have answered my own question by properly looking into what XMLHttpRequest() & JSON.parse() does.
If someone is looking to hook a JSON file into https://www.chartjs.org/ charts then the below might help.
The JSON file
"comms_by_month":[
{
"name": "July",
"month":7,
"count":0
},
{
"name": "August",
"month":8,
"count":1652
},
{
"name": "September",
"month":9,
"count":600
},
{
"name": "October",
"month":10,
"count":0
},
{
"name": "November",
"month":11,
"count":0
},
{
"name": "December",
"month":12,
"count":0
}
]
Get the JSON file into a var
<script>
// Set the var for the json file located on the web server
var jsonFile_dash_comms_by_month = 'http://hostname/portal/js/export_json/dash-comms-by-month.json';
var request = new XMLHttpRequest();
request.open("GET",jsonFile_dash_comms_by_month,false);
request.send(null)
var jsonObj_dash_comms_by_month = JSON.parse(request.responseText);
</script>
A div where the chart will be displayed
<div class="ca-comms-by-month"></div>
Functions to get the labels and datasets into a var
<script>
var labels = jsonObj_dash_comms_by_month.comms_by_month.map(function(e) {
return e.name;
});
var data = jsonObj_dash_comms_by_month.comms_by_month.map(function(e) {
return e.count;
});
</script>
Function to create the CharJS config
See (http://www.chartjs.org/docs/latest/configuration/) for more about ChartJs config.
<script>
function createConfig(details, data) {
return {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Comms count by month',
steppedLine: details.steppedLine,
data: data,
borderColor: details.color,
fill: true,
}]
},
options: {
responsive: true,
title: {
display: false,
text: details.label,
},
tooltips: {
enabled:true, // Disable this for custom tool tips || http://www.chartjs.org/docs/latest/configuration/tooltip.html
mode: 'index',
intersect: false,
cornerRadius:0
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Count'
},
ticks: {
beginAtZero:true
}
}]
},
legend: {
display: false, // False to hide the legdend dataset tile
labels: {
fontColor: 'rgb(255, 99, 132)'
}
}
}
};
}<script>
On load function to display the chart
<script>
window.onload = function()
{
var container = document.querySelector('.ca-comms-by-month');
var steppedLineSettings = [{
steppedLine:false,
label: '',
color: window.chartColors.purple
}];
steppedLineSettings.forEach(function(details) {
var div = document.createElement('div');
div.classList.add('chart-container');
var canvas = document.createElement('canvas');
div.appendChild(canvas);
container.appendChild(div);
var ctx = canvas.getContext('2d');
var config = createConfig(details, data);
new Chart(ctx, config);
});
};
</script>
This gave me the below chart
I would be keen to hear from anyone who can point out any improvements on the above. I am expecting to have 10+ charts on a dashboard type page.
Thanks
edwoli

Categories

Resources