I using Chart.js and I want to pull the data from the properties inside the DIV element.
I can get data in data-gpget and data-gpret. It writes to the console but does not see it as "data" data.
data: getATT('#graph3','data-gpval') and data: getATT('#graph3','data-gpret')
What could be the reason for this? What am I missing?
Thank you.
<div id="graph3" data-gpget="[28,12,14,27,11]" data-gpret="[21,64,32,73,76]">
<canvas id="js-chartjs-earnings"></canvas>
</div>
JS:
function getATT(id,value) {
return $(id).attr(value);
}
return e = a, t = [{
key: "initCharts", value: function () {
Chart.defaults.scale.gridLines.color = "transparent", Chart.defaults.scale.gridLines.zeroLineColor = "transparent", Chart.defaults.scale.ticks.beginAtZero = !0, Chart.defaults.global.elements.line.borderWidth = 0, Chart.defaults.global.elements.point.radius = 0, Chart.defaults.global.elements.point.hoverRadius = 0, Chart.defaults.global.tooltips.cornerRadius = 3, Chart.defaults.global.legend.labels.boxWidth = 12;
var r, a = jQuery(".js-chartjs-earnings");
r = {
labels: ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"],
datasets: [{
label: "GETTING",
fill: !0,
data: getATT('#graph3','data-gpget')
}, {
label: "RETURNS",
fill: !0,
data: getATT('#graph3','data-gpret')
}]
}, a.length && new Chart(a, {
type: "bar",
data: r,
options: {
tooltips: {
intersect: !1, callbacks: {
label: function (r, a) {
return a.datasets[r.datasetIndex].label + ": $" + r.yLabel
}
}
}
}
})
}
}, {
key: "init", value: function () {
this.initCharts()
}
}], null && r(e.prototype, null), t && r(e, t), a
the attr method will always return a string.
try using the data method instead...
return $(id).data(value);
just be sure to remove the data- prefix from the attribute names.
see / run following example...
var testATT = getATT('#graph3','data-gpget');
var testData = getData('#graph3','gpget');
console.log(typeof testATT, testATT);
console.log(typeof testData, testData);
function getData(id,value) {
return $(id).data(value);
}
function getATT(id,value) {
return $(id).attr(value);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="graph3" data-gpget="[28,12,14,27,11]" data-gpret="[21,64,32,73,76]">
<canvas id="js-chartjs-earnings"></canvas>
</div>
Related
first, thanks a lot for all the help from stackoverflow.
I'm trying to display charts which have Data spreaded according to the amount of time between data points. https://www.chartjs.org/docs/latest/axes/cartesian/time.html
so: X Axis: ---2022-02-01-----------2022-02-05-----------2022-02-07----------
My object:
X Axis: ---2022-02-01-----------2022-02-03-----------2022-02-04-----------
but the challenge is that the datas are not coming from the HTML code with x and y like this:
data: [{
x: '2022-02-01',
y: 25
}, {
x: '2022-02-05',
y: -25
}, {
x: '2022-02-07',
y: -225
}]
but from a CSV file.
So i don't know how to set the xAxis scale config with time.
Please somebody know how to solve it?
Thanks a lot.
<script>
d3.csv("example.csv").then(makeChart);
function makeChart(players) {
var dateData = players.map(function (d) {
return d.date;
});
var btcData = players.map(function (d) {
return d.btc;
});
var VETData = players.map(function (d) {
return d.vet;
});
var totalData = players.map(function (d) {
return d.total;
});
var BTCColors = players.map(function(d) {
return d.btc < 0 ? '#F15F36' : '#19A0AA';
});
var VETColors = players.map(function(d) {
return d.vet < 0 ? '#F15F36' : '#19A0AA';
});
var TOTALColors = players.map(function(d) {
return d.total < 0 ? '#F15F36' : '#19A0AA';
});
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: dateData,
datasets: [{
type: 'bar',
label: 'BTCUSDT',
borderColor: BTCColors,
backgroundColor:BTCColors,
data: btcData
}, {
type: 'bar',
label: 'VETUSDT',
data: VETData,
borderColor: VETColors,
backgroundColor: VETColors
}, {
type: 'line',
label: 'TOTAL',
data: totalData,
borderColor: '#F15F36',
backgroundColor: '#19A0AA',
borderWidth : 1,
pointRadius : 1.1,
fill:false
}]
}
}
);
const config = {
type: 'scatter',
data: data,
options: {
scales: {
x: {
type: 'time',
time:{
unit:'day'
}
}
}
}
}
};
</script>
js src:
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"
integrity="sha512-d9xgZrVZpmmQlfonhQUvTR7lMPtO7NkZMkA0ABN3PHCbKA5nqylQ/yWlFAyY6hYgdF1Qh6nYiuADWwKB4C2WSw=="
crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
my csv file:
date,btc,vet,total
2022-02-01,25,0,25
2022-02-05,0,-50,-25
2022-02-07,-200,0,-225
2022-02-20,-0,100,-125
2022-03-01,0,150,25
2022-03-15,400,0,425
2022-04-01,-100,0,325
2022-04-15,0,-10,315
2022-06-01,500,0,815
2022-07-01,0,200,1015
chart preview
Okay i find the answer, had to convert the CSV into Arrays, and arrays into data structure:
<script>
drawChart();
async function drawChart(){
const dataArray = await getData();
const BTCdatapoints = dataArray.DATEdata.map((day,index) => {
let dayObject = {};
dayObject.x = dataArray.DATEdata[index];
dayObject.y = dataArray.BTCdata[index];
return dayObject
})
const VETdatapoints = dataArray.DATEdata.map((day,index) => {
let dayObject = {};
dayObject.x = dataArray.DATEdata[index];
dayObject.y = dataArray.VETdata[index];
return dayObject
})
const TOTALdatapoints = dataArray.DATEdata.map((day,index) => {
let dayObject = {};
dayObject.x = dataArray.DATEdata[index];
dayObject.y = dataArray.TOTALData[index];
return dayObject
})
const data = {datasets: [{
label: 'BTCUSDT',
data: BTCdatapoints
}, {
type: 'bar',
label: 'VETUSDT',
data: VETdatapoints
}, {
type: 'line',
label: 'TOTAL',
data: TOTALdatapoints
}]
}
const config = {
type: 'bar',
data,
options: {
scales: {
x: {
type: "time",
time: {
unit: "day"
}
},
y:{
beginAtZero : true
}
}
}
};
const myChart = new Chart(
document.getElementById("myChart"),
config
);
};
async function getData() {
const DATEdata = [];
const BTCdata = [];
const VETdata = [];
const TOTALData = [];
const url ='example.csv';
const response = await fetch(url);
const tabledata = await response.text();
const table = tabledata.split('\r\n').splice(1);
table.forEach(row =>{
const column = row.split(',');
const date = column[0];
const BTC = column[1];
const VET = column[2];
const TOTAL = column[3];
DATEdata.push(date);
BTCdata.push(BTC);
VETdata.push(VET);
TOTALData.push(TOTAL);
});
return {DATEdata,BTCdata,VETdata,TOTALData};
}
</script>
JS SRC:
<script src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/papaparse#5.3.2/papaparse.min.js"></script>
The issue detail:
1. I implement the feature with the vue-slider-component module, but that has a lot of warnings when I move the dots on the slider.
2. I know that the reason is that I used v-for to point to an object that will change, but I do not know how to fix this issue.
the following link is my test site:
https://jsfiddle.net/ncwv84x9/
enter image description here
My codes:
code1 (Html)
<div id="app">
<div class="box" v-for="(item,index) in columnvalue">
<label>{{item.text}}</label>
<input v-model="value[index]" />
</div>
<hr />
<br />
<vue-slider v-model="value" :order="false" :tooltip="'always'" :process="false" :marks="marks" :width="600">
<template slot="tooltip" slot-scope="{index}">
<div>{{getText(index)}}</div>
</template>
</vue-slider>
</div>
JavaScript + Vue:
new Vue({
el: '#app',
components: {
VueSlider: window['vue-slider-component']
},
data: function() {
return {
// collect the all values
columnvalue: [],
// stored disease value
pet_name: [{
text: 'dog',
index: 0
},
{
text: 'cat',
index: 1
}
],
// stored drug value
feeder_name: [{
text: 'Sam',
index: 0
}],
// from age filter
age: [
65, 100
],
test: "",
value: [],
process: dotsPos => [
[dotsPos[0], dotsPos[1], {
backgroundColor: 'pink'
}],
[dotsPos[1], dotsPos[2], {
backgroundColor: 'blue'
}],
[dotsPos[2], dotsPos[3], {
backgroundColor: 'black'
}],
],
after: {},
relations: [],
marks: {
'0': {
label: 'start',
margin: '0 0 0 10px'
},
'100': {
label: 'end',
labelStyle: {
left: '100%',
margin: '0 0 0 10px',
top: '50%',
transform: 'translateY(-50%)'
}
}
}
}
},
created: function() {
//vue instance 被 constructor 建立後,在這裡完成 data binding
let tmpArray = this.pet_name.concat(this.feeder_name);
let tmpValueArray = [];
for (i = 0; i < tmpArray.length; i++) {
tmpArray[i].index = i;
tmpValueArray.push(0);
}
this.columnvalue = tmpArray;
this.value = tmpValueArray;
},
methods: {
getText(index) {
const ani = this.columnvalue.find((v) => v.index == index).text;
this.after = {
...this.after,
[ani]: this.value[index]
}
return ani;
},
getNodeRelation() {
const indexs = this.after;
let result = [];
let result2 = [];
let placement = [];
for (obj in indexs) {
placement.push([obj, indexs[obj]]);
}
placement.sort(function(a, b) {
/* console.log(a[1]) */
return a[1] - b[1];
})
for (i = 0; i < placement.length; i++) {
if (i + 1 >= placement.length) {
break;
}
let distance = placement[i + 1][1] - placement[i][1];
let predicate = "";
if (distance > 0) {
predicate = "after";
} else if (distance == 0 && placement[i + 1][1] == 0) {
predicate = "hasUse";
} else {
predicate = "same";
}
let source = {
label: placement[i][0],
index: i
};
let target = {
label: placement[i + 1][0],
index: i
};
// store the 4-tuple reprsentations about slider
result2.push({
source: source,
target: target,
type: predicate,
days: distance
});
}
/* this.relations = "{\"relation\":" + JSON.stringify(result2)+"}" */
;
this.relations = JSON.stringify(result2);
},
getAllFilters() {
let vm = this;
let beginHas = true;
if (vm.relations.length == 0) {
vm.getNodeRelation();
beginHas = false;
}
let result = {
age: vm.age,
disease_name: vm.disease_name,
drug_name: vm.drug_name,
relation: vm.relations
};
if (!beginHas) {
vm.relations = [];
}
this.test = JSON.stringify(result);
}
},
})
I get a infinite loop error which disappears when I remove this section in getText()
this.after = {
...this.after,
[ani]: this.value[index]
}
This is because there is some reactivity triggered and re-renders the dom, which calls that function, which renders the dom and so on...
I am creating a chart with Chartist.js. I'm getting json data with the Google embed API. I have a problem with this one. The array works with the values I give. But it does not work for data from json.
my code :
var TotalBrowser = [];
var BrowserSeries = [];
var oxyn = {
queryAnalytics: function() {
var id = '164690638';
var expressions = [{
expression: 'ga:hits'
}];
var dimension = [{
name: 'ga:browser'
}];
oxyn.getReportQuery(id, '7daysago', 'today', expressions, dimension).then(function(response) {
var formattedJson = JSON.stringify(response.result, null, 2);
var data = JSON.parse(formattedJson);
var i = 0;
BrowserTotal = data.reports[0].data.totals[0].values[0];
jQuery(data.reports[0].data.rows).each(function() {
if (i <= 3) {
jQuery('#Browsers').append(browsericon[i] + this.dimensions[0]);
var percent = (parseInt(this.metrics[0].values[0]) / parseInt(BrowserTotal)) * 100;
BrowserSeries.push(Math.round(percent));
TotalBrowser.push(Math.round(percent) + '%');
i++;
}
});
demo.initChartist();
});
}
}
var demo = {
initChartist: function() {
var dataPreferences = {
series: [
[BrowserSeries.join()]
]
};
var optionsPreferences = {
donut: true,
donutWidth: 40,
startAngle: 0,
total: 100,
showLabel: false,
axisX: {
showGrid: false
}
};
Chartist.Pie('#chartPreferences', dataPreferences, optionsPreferences);
Chartist.Pie('#chartPreferences', {
labels: [TotalBrowser.join()],
series: [BrowserSeries.join()]
});
console.log(BrowserSeries.join());
}
};
it does not work that way. But if I write the code like this, it works.
Chartist.Pie('#chartPreferences', {
labels: [TotalBrowser.join()],
series: [30, 70]
});
and this is working.
Chartist.Pie('#chartPreferences', {
labels: [TotalBrowser[0], TotalBrowser[1]],
series: [BrowserSeries[0], BrowserSeries[1]]
});
console output
console.log(BrowserSeries.join());
30,70
JSON Source
It's a very silly problem.
yes I finally solved it. I write for those who have the same problem.
Chartist.Pie('#chartPreferences', {
labels: TotalBrowser,
series: BrowserSeries
});
We need to remove [ ] characters. We must also send the data directly to the array.
Also : https://github.com/gionkunz/chartist-js/issues/738
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
I need to search for an element in a json object like this:
var new_a = 'new';
var json = { cells:
[ { type: 'model',
id: '5aef826a1809',
attrs: {
text: 'first',
a: 'changethis'
}
},
{ type: 'model',
id: '2c11b8bd8112',
attrs: {
text: 'second'
}
}
]
}
Now I want to find the object with the id = 5aef826a1809, because I want to change the value of a to new_a or insert an a-element if it doesn't exist.
If id = 2c11b8bd8112 a new a-element with the content new_a should be added.
I tried to use
var res = _.find(json.cells, { id: '5aef826a1809' }); // doesn't work
res.attrs.a = new_a; // this would update or add new field, right?
But this doesn't work
Try like this
var new_a = 'new';
var json = {
cells: [{
type: 'model',
id: '5aef826a1809',
attrs: {
text: 'first',
a: 'changethis'
}
}, {
type: 'model',
id: '2c11b8bd8112',
attrs: {
text: 'second'
}
}]
};
var obj = json.cells.find(function (x) {
return x.id == '5aef826a1809'
});
if (obj) { // return value if found else return undefined if not found
obj.attrs.a = new_a;
console.log(json);
}
JSFIDDLE
Using this simple for loop should work, if that's what you're looking for:
for(var i = 0; i<json.cells.length; i++){
if(json.cells[i].id == "5aef826a1809" || json.cells[i].id == "2c11b8bd8112"){
json.cells[i].attrs.a = "new_a";
}
}
Hope it helped.
You can use Array.prototype.some for searching, changing and for making a short circuit to prevent more iteration than necessary.
var new_a = 'new',
json = {
cells: [{
type: 'model',
id: '5aef826a1809',
attrs: {
text: 'first',
a: 'changethis'
}
}, {
type: 'model',
id: '2c11b8bd8112',
attrs: {
text: 'second'
}
}]
};
function change(id) {
json.cells.some(function (a) {
var i = id.indexOf(a.id);
if (~i) {
a.attrs = a.attrs || {};
a.attrs.a = new_a;
id.splice(i, 1);
if (!id.length) {
return true;
}
}
});
}
change(['5aef826a1809', '2c11b8bd8112']);
document.write('<pre>' + JSON.stringify(json, 0, 4) + '</pre>');