Chart.js is only displaying after f12 is pressed - javascript

I'm trying to display a stock chart on the webpage when it is opened, but it won't display unless i press f12
I've already tried including the code inside a function and displaying the chart when a button is pressed but it also doesn't seem to work
<script type="text/javascript">
var highlist = [];
var lowlist = [];
var datelist = [];
$.getJSON("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=G9UIQ9K1TRVBHHME", function(json) {
var times = json["Time Series (Daily)"];
for(var time in times)
{
var stock_info = times[time];
var highItem = stock_info["2. high"];
var lowItem = stock_info["3. low"];
highlist.push(highItem);
lowlist.push(lowItem);
datelist.push(time);
}
});
var ctx = document.getElementById("lineChart").getContext('2d');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: datelist,
datasets: [{
label: "My First dataset",
label: "High",
backgroundColor: [
'rgba(204, 204, 255, .2)',
],
borderColor: [
'rgba(51, 51, 255, .7)',
],
borderWidth: 2,
data: highlist
},
{
label: "Low",
backgroundColor: [
'rgba(0, 137, 132, .2)',
],
borderColor: [
'rgba(0, 10, 130, .7)',
],
data: lowlist
}]
},
});
</script>
Expect the chart to show but nothing is displaying unless f12 is pressed

The getJson is an asynchronous function, so JS will send a request and then draw your chart before it gets a response.
Put all the chart stuff inside a function, and then call that function after the for loop inside your getJson callback.

Related

json file to charts

I'm doing a project which is to extract data from python and show it in jsp dashboard.
I'm trying to load a json file to chartjs but it's not giving result
<script>
$.getJSON("resources/json_test.json", function(data) {
var labels = data.department.map(function(e) {
return e[1];
});
var data = data.volunteer.map(function(e) {
return e[1];
});
var context = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(context, {
type : 'bar',
data : {
labels : labels,
datasets : [ {
label : 'volunteer',
lineTension : 0.1,
data : data,
backgroundColor : "rgba(255, 99, 132, 0.2)"
}]
}
});
});
{"department":{"0":"IT","1":"Math","2":"English","3":"Software","4":"Game"},"volunteer":{"0":409,"1":1781,"2":476,"3":550,"4":562}}
To call .map() the datastructure needs to be an array, and since yours are objects it aint working, if you change your code to this it should work:
const labels = Object.values(data.department)
const parsedData = Object.values(data.volunteer)
const context = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(context, {
type: 'bar',
data: {
labels: labels,
datasets: [ {
label: 'volunteer',
lineTension: 0.1,
data: parsedData,
backgroundColor: "rgba(255, 99, 132, 0.2)"
}]
}
});

How can I highlight a particular datapoint in chartjs, where my data is coming from json array?

// here I am taking another json encoded data from phpfile
$(document).ready(function () {
showGraph();
});
function showGraph()
{
{
$.post("phpfile.php",
function (data)
{
console.log(data);
var name = [];
var marks = [];
var height=[];
//and here as I couldn't encode two json array's separetly I'm declaring it to a variable and then using it
var jsonfile =[{"height":"85","st_name":"Name1"},{"height":"100","st_name":"Name3"},{"height":"92","st_name":"Name4"},{"height":"104","st_name":"Name5"},{"height":"91","st_name":"Name2"},{"height":"99","st_name":"Name6"},{"height":"140","st_name":"AI346"},{"height":"139","st_name":"abc"},{"height":"141","st_name":"def"},{"height":"140","st_name":"ghi"},{"height":"144","st_name":"jkl"},{"height":"130","st_name":"lmn"},{"height":"142","st_name":"opq"},{"height":"132","st_name":"rst"},{"height":"135","st_name":"xyz"},{"height":"135","st_name":"asdfsf"}];
//here I am reading the data from phpfile(1st Json array)
for (var i in data) {
name.push(data[i].st_name);
marks.push(data[i].height);
}
//here i am trying to access data from second json
for (var i=0;i<jsonfile.length;i++){
if(jsonfile[i].height==100)
{ height.push(jsonfile[i].height)}
}
//my graph function ,when I do this I am getting a single point with second json(height variable) but I need to highlight the particular point under a condition... I am not understanding how to do it.
var chartdata = {
labels: name,
datasets: [
{
label: 'height',
fill:false,
lineTension:0.5,
backgroundColor: '#5B2C6F',
borderColor: '#5B2C6F',
pointHoverBackgroundColor: '#5B2C6F',
pointHoverBorderColor: '#5B2C6F',
data: marks
//data:height
},
{
label: 'weight',
fill:false,
lineTension:0.1,
backgroundColor: '#C0392B',
borderColor: '#C0392B',
pointHoverBackgroundColor: '#C0392B',
pointHoverBorderColor: '#C0392B',
data:height,
//data:height
}
]
};
var graphTarget = $("#graphCanvas");
var lineGraph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options :{
scales:{
xAxes: [{
display: false //this will remove all the x-axis grid lines
}]
}
}
});
});
}
}
</script>
i will try to improve this.
var data =[{"height":"85","st_name":"Name1","color":"rgba(85, 85, 255, 255)"},{"height":"100","st_name":"Name3","color":"rgba(255, 0, 0, 2)"},{"height":"92","st_name":"Name4","color":"rgba(85, 85, 255, 255)"},{"height":"104","st_name":"Name5","color":"rgba(85, 85, 255, 255)"}];
var height = [];
var label = [];
var color = [];
for(i = 0; i<data.length; i++){
height.push(data[i]['height']);
label.push(data[i]['st_name']);
color.push(data[i]['color']);
}
var ctx = document.getElementById('myLine').getContext('2d');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: label,
datasets: [{
data: height,
pointBorderColor: color,
}]
}
});

I want to change color of individual bar of bar graph

I am getting data from mysql using php to populate the array and then using that result to fill chart data. I want to change the color of the bars which are greater than 50. I tried a few examples that are already on the stack-overflow, however I was unable to solve my problem. That is why I am now asking this question.
$(document).ready(function() {
$.ajax({
url: "http://localhost:8080/chartjs/data.php",
method: "GET",
success: function(data) {
console.log(data);
var player = [];
var score = [];
for (var i in data) {
player.push(data[i].y);
score.push(data[i].x);
}
var chartdata = {
labels: player,
datasets: [{
label: 'Records from mysql',
backgroundColor: 'rgb(92, 95, 102)',
borderColor: 'rgba(200, 200, 200, 0.75)',
hoverBackgroundColor: 'rgba(30, 0, 200)',
hoverBorderColor: 'rgba(200, 200, 197)',
data: score
}
]
};
var ctx = $("#mycanvas");
var barGraph = new Chart(ctx, {
type: 'bar',
colors: {
data: function(score) {
return (score.value >= 45) ? '#00ff00' : '#f90411';
}
},
data: chartdata
});
},
error: function(data) {
console.log(data);
}
});
});
#chart-container {
width: 640px;
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<div id="chart-container">
<canvas id="mycanvas"></canvas>
</div>
From what I could figure out is that your question is mostly related to the usage of chart.js. My solution to your problem would look like the following:
//Load your data (obviously this is a hardcoded example, you could use any backend code like PHP):
let data = [12, 19, 74, 38, 45, 62];
//Insantiate fields you would like to use, such as `colors` for background color and `borderColors` for, you guessed it, the color of the borders:
let colors = [];
let borderColors = [];
//Set the field values based on value (this would be your logic):
$.each(data, function(index, value) {
//When the value is higher than 45, set it to given color, else make them the other color (in the example the bars would appear red-ish):
if(value > 45) {
colors[index] = "rgba(0, 255, 0, 0.2)";
borderColors[index] = "rgba(0, 255, 1)";
}
else {
colors[index] = "rgba(249, 4, 17, 0.2)";
borderColors[index] = "rgba(249, 4, 17, 1)";
}
});
//Any code related to creating the chart with the bars (you could find any documentation regarding this code on the homepage of Chart.js):
let ctx = document.getElementById('myChart');
let myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['1', '2', '3', '4', '5', '6'],
datasets: [{
label: 'Records from mysql',
//Populate your fields here:
data: data,
backgroundColor: colors,
borderColor: borderColors,
hoverBackgroundColor: 'rgba(30, 0, 200)',
hoverBorderColor: 'rgba(200, 200, 197)',
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
#chart-container {
width: 640px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<div id="chart-container">
<canvas id="myChart"></canvas>
</div>
JSFiddle
I applied some code I found on the following post on Github:
$.each(data, function(index, value) {
//When the value is higher than 45, set it to given color, else make them the other color (in the example the bars would appear red-ish):
if(value > 45) {
colors[index] = "rgba(0, 255, 0, 0.2)";
borderColors[index] = "rgba(0, 255, 1)";
}
else {
colors[index] = "rgba(249, 4, 17, 0.2)";
borderColors[index] = "rgba(249, 4, 17, 1)";
}
});
If anyone knows a more clean solution, please let me know in the comments.

Chart.js not showing data until I click on the label 3 times

I'm adding a chart in a website and I'm having a weird issue with chart.js. I'm loading the data from 2 arrays that are created when the page is loaded from a json file.
The issue is that the data it's not showing until I click on the label of the chart 2 times. At load, there is no info, 1st click x labels are showing up and in 2nd click both, x labels and data are showing up. After that, clicking on the label of the dataset work as expected.
I assumed my problem was that I was loading the data before the chart exists, so, my idea was to encapsulate everything in a function and call it when clicking a button that shows the chart, but it's keeping doing the same thing. How would you fix it?
Here is my html related code:
<div class="popup">
<span class="popuptrend" id="myPopup"><canvas id="myChart" width="auto" height="400"></canvas></span>
</div>
And my JS code:
$(function(){
$("#showTrend").click(function(){
createChart();
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
});
});
function createChart(){
var labels = [];
var dataValue = [];
$.getJSON("./resources/chart.json", function(jsonData) {
var index = 0;
for (var key in jsonData) {
if(index == 0){ // SKIP FISRT ITEM
index++;
}else{
labels.push(key);
dataValue.push(parseFloat(jsonData[key]));
}
}
});
var dataVar = {
labels: labels,
datasets:
[{
label: "Value",
backgoundColor: 'rgba(255, 0, 0, 0.2)',
borderColor: 'rgba(255, 0, 0, 0.8)',
borderWith: 1,
data: dataValue
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: dataVar,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
And a extract from my data json file:
{
"15/04/2017":"67.34375",
"16/04/2017":"67.3203125",
}
And a gif of the behaviour.
Thanks!
Since $.getJSON() method is asynchronous, you should construct your chart inside it­'s callback function, like so :
...
$.getJSON("./resources/chart.json", function(jsonData) {
var index = 0;
for (var key in jsonData) {
if (index == 0) { // SKIP FISRT ITEM
index++;
} else {
labels.push(key);
dataValue.push(parseFloat(jsonData[key]));
}
}
var dataVar = {
labels: labels,
datasets: [{
label: "Value",
backgoundColor: 'rgba(255, 0, 0, 0.2)',
borderColor: 'rgba(255, 0, 0, 0.8)',
borderWith: 1,
data: dataValue
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: dataVar,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
});
...
Hopefully, this will solve your problem.
As I posted before as a comment, try doing like this:
$.getJSON(...).done(var dataVar....)

Click events on Pie Charts in Chart.js

I've got a question regard Chart.js.
I've drawn multiple piecharts using the documentation provided. I was wondering if on click of a certain slice of one of the charts, I can make an ajax call depending on the value of that slice?
For example, if this is my data
var data = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
}
],
is it possible for me to click on the Red labelled slice and call a url of the following form:
example.com?label=red&value=300? If yes, how do I go about this?
Update: As #Soham Shetty comments, getSegmentsAtEvent(event) only works for 1.x and for 2.x getElementsAtEvent should be used.
.getElementsAtEvent(e)
Looks for the element under the event point, then returns all elements
at the same data index. This is used internally for 'label' mode
highlighting.
Calling getElementsAtEvent(event) on your Chart instance passing an
argument of an event, or jQuery event, will return the point elements
that are at that the same position of that event.
canvas.onclick = function(evt){
var activePoints = myLineChart.getElementsAtEvent(evt);
// => activePoints is an array of points on the canvas that are at the same position as the click event.
};
Example: https://jsfiddle.net/u1szh96g/208/
Original answer (valid for Chart.js 1.x version):
You can achieve this using getSegmentsAtEvent(event)
Calling getSegmentsAtEvent(event) on your Chart instance passing an
argument of an event, or jQuery event, will return the segment
elements that are at that the same position of that event.
From: Prototype Methods
So you can do:
$("#myChart").click(
function(evt){
var activePoints = myNewChart.getSegmentsAtEvent(evt);
/* do something */
}
);
Here is a full working example:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.2.js"></script>
<script type="text/javascript" src="Chart.js"></script>
<script type="text/javascript">
var data = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
}
];
$(document).ready(
function () {
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx).Pie(data);
$("#myChart").click(
function(evt){
var activePoints = myNewChart.getSegmentsAtEvent(evt);
var url = "http://example.com/?label=" + activePoints[0].label + "&value=" + activePoints[0].value;
alert(url);
}
);
}
);
</script>
</head>
<body>
<canvas id="myChart" width="400" height="400"></canvas>
</body>
</html>
Using Chart.JS version 2.1.3, answers older than this one aren't valid anymore.
Using getSegmentsAtEvent(event) method will output on console this message:
getSegmentsAtEvent is not a function
So i think it must be removed. I didn't read any changelog to be honest. To resolve that, just use getElementsAtEvent(event) method, as it can be found on the Docs.
Below it can be found the script to obtain effectively clicked slice label and value. Note that also retrieving label and value is slightly different.
var ctx = document.getElementById("chart-area").getContext("2d");
var chart = new Chart(ctx, config);
document.getElementById("chart-area").onclick = function(evt)
{
var activePoints = chart.getElementsAtEvent(evt);
if(activePoints.length > 0)
{
//get the internal index of slice in pie chart
var clickedElementindex = activePoints[0]["_index"];
//get specific label by index
var label = chart.data.labels[clickedElementindex];
//get value by index
var value = chart.data.datasets[0].data[clickedElementindex];
/* other stuff that requires slice's label and value */
}
}
Hope it helps.
Chart.js 2.0 has made this even easier.
You can find it under common chart configuration in the documentation. Should work on more then pie graphs.
options:{
onClick: graphClickEvent
}
function graphClickEvent(event, array){
if(array[0]){
foo.bar;
}
}
It triggers on the entire chart, but if you click on a pie the model of that pie including index which can be used to get the value.
Working fine chartJs sector onclick
ChartJS : pie Chart - Add options "onclick"
options: {
legend: {
display: false
},
'onClick' : function (evt, item) {
console.log ('legend onClick', evt);
console.log('legd item', item);
}
}
I was facing the same issues since several days, Today i have found the solution. I have shown the complete file which is ready to execute.
<html>
<head><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js">
</script>
</head>
<body>
<canvas id="myChart" width="200" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
onClick:function(e){
var activePoints = myChart.getElementsAtEvent(e);
var selectedIndex = activePoints[0]._index;
alert(this.data.datasets[0].data[selectedIndex]);
}
}
});
</script>
</body>
</html>
If using a Donught Chart, and you want to prevent user to trigger your event on click inside the empty space around your chart circles, you can use the following alternative :
var myDoughnutChart = new Chart(ctx).Doughnut(data);
document.getElementById("myChart").onclick = function(evt){
var activePoints = myDoughnutChart.getSegmentsAtEvent(evt);
/* this is where we check if event has keys which means is not empty space */
if(Object.keys(activePoints).length > 0)
{
var label = activePoints[0]["label"];
var value = activePoints[0]["value"];
var url = "http://example.com/?label=" + label + "&value=" + value
/* process your url ... */
}
};
If you are using TypeScript, the code is a little funky because there is no type inference, but this works to get the index of the data that has been supplied to the chart:
// events
public chartClicked(e:any):void {
//console.log(e);
try {
console.log('DS ' + e.active['0']._datasetIndex);
console.log('ID ' + e.active['0']._index);
console.log('Label: ' + this.doughnutChartLabels[e.active['0']._index]);
console.log('Value: ' + this.doughnutChartData[e.active['0']._index]);
} catch (error) {
console.log("Error In LoadTopGraph", error);
}
try {
console.log(e[0].active);
} catch (error) {
//console.log("Error In LoadTopGraph", error);
}
}
To successfully track click events and on what graph element the user clicked, I did the following in my .js file I set up the following variables:
vm.chartOptions = {
onClick: function(event, array) {
let element = this.getElementAtEvent(event);
if (element.length > 0) {
var series= element[0]._model.datasetLabel;
var label = element[0]._model.label;
var value = this.data.datasets[element[0]._datasetIndex].data[element[0]._index];
}
}
};
vm.graphSeries = ["Series 1", "Serries 2"];
vm.chartLabels = ["07:00", "08:00", "09:00", "10:00"];
vm.chartData = [ [ 20, 30, 25, 15 ], [ 5, 10, 100, 20 ] ];
Then in my .html file I setup the graph as follows:
<canvas id="releaseByHourBar"
class="chart chart-bar"
chart-data="vm.graphData"
chart-labels="vm.graphLabels"
chart-series="vm.graphSeries"
chart-options="vm.chartOptions">
</canvas>
var ctx = document.getElementById('pie-chart').getContext('2d');
var myPieChart = new Chart(ctx, {
// The type of chart we want to create
type: 'pie',
});
//define click event
$("#pie-chart").click(
function (evt) {
var activePoints = myPieChart.getElementsAtEvent(evt);
var labeltag = activePoints[0]._view.label;
});
You can add in the options section an onClick function, like this:
options : {
cutoutPercentage: 50, //for donuts pie
onClick: function(event, chartElements){
if(chartElements){
console.log(chartElements[0].label);
}
},
},
the chartElements[0] is the clicked section of your chart, no need to use getElementsAtEvent anymore.
It works on Chart v2.9.4
I have an elegant solution to this problem. If you have multiple dataset, identifying which dataset was clicked gets tricky. The _datasetIndex always returns zero.
But this should do the trick. It will get you the label and the dataset label as well.
Please note ** this.getElementAtEvent** is without the s in getElement
options: {
onClick: function (e, items) {
var firstPoint = this.getElementAtEvent(e)[0];
if (firstPoint) {
var label = firstPoint._model.label;
var val = firstPoint._model.datasetLabel;
console.log(label+" - "+val);
}
}
}
Within options place your onclick and call the function you need as an example the ajax you need, I'll leave the example so that every click on a point tells you the value and you can use it in your new function.
options: {
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
color: 'white',
//backgroundColor:'#ffce00',
align: 'start'
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true,
fontColor: "white"
},gridLines: {
color: 'rgba(255,255,255,0.1)',
display: true
}
}],
xAxes: [{
ticks: {
fontColor: "white"
},gridLines: {
display: false
}
}]
},
legend: {
display: false
},
//onClick: abre
onClick:function(e){
var activePoints = myChart.getElementsAtEvent(e);
var selectedIndex = activePoints[0]._index;
alert(this.data.datasets[0].data[selectedIndex]);
}
}

Categories