I am using the ZingChart library to graph results from an API call. When I pass in a normal array for the "values" field of the chart data object, everything works fine. However, when I pass in an array made from Object.keys(titleSet) (where titleSet is a normal Javascript object), the graph displays as follows:
Example Chart
As you can see, the x-axis is now labeled with numbers instead of the array of strings. But when I print out the the result of Object.keys(titleSet) vs. passing in a normal array, they both appear to be the same in the console. Can anyone help me figure out what I'm doing wrong?
//List of movies inputted by the user
var movieList = [];
var movieSet = {};
var IMDBData = {
"values": [],
"text": "IMDB",
};
var metascoreData = {
"values": [],
"text": "Metascore"
};
var RTMData = {
"values": [],
"text": "Rotten Tomatoes Meter"
};
var RTUData = {
"values": [],
"text": "Rotten Tomatoes User"
};
var chartData = {
"type":"bar",
"legend":{
"adjust-layout": true
},
"plotarea": {
"adjust-layout":true
},
"plot":{
"stacked": true,
"border-radius": "1px",
"tooltip": {
"text": "Rated %v by %plot-text"
},
"animation":{
"effect":"11",
"method":"3",
"sequence":"ANIMATION_BY_PLOT_AND_NODE",
"speed":10
}
},
"scale-x": {
"label":{ /* Scale Title */
"text":"Movie Title",
},
"values": Object.keys(movieSet) /* Needs to be list of movie titles */
},
"scale-y": {
"label":{ /* Scale Title */
"text":"Total Score",
}
},
"series":[metascoreData, IMDBData, RTUData, RTMData]
};
var callback = function(data)
{
var resp = JSON.parse(data);
movieSet[resp.Title] = true;
//Render
zingchart.render({
id:'chartDiv',
data:chartData,
});
};
Full Disclosure, I'm a member of the ZingChart team.
Thank you for updating your question. The problem is you have defined your variable movieSet before the variablechartData. When parsing the page, top down, it is executing Object.keys({}) on an empty object when creating the variable chartData. You should just directly assign it into your config later on chartData['scale-x']['values'] = Object.keys(moviSet).
var callback = function(data)
{
var resp = JSON.parse(data);
movieSet[resp.Title] = true;
//Render
zingchart.render({
id:'chartDiv',
data:chartData,
});
};
There is a problem with the above code as well. It seems you are calling render on the chart every time you call this API. You should have one initial zingchart.render() and then from there on out use our API. I would suggest setdata method as it replaces a whole new JSON packet or modify method.
I am making some assumptions on how you are handling data. Regardless, check out the following demo
var movieValues = {};
var myConfig = {
type: "bar",
scaleX:{
values:[]
},
series : [
{
values : [35,42,67,89,25,34,67,85]
}
]
};
zingchart.render({
id : 'myChart',
data : myConfig,
height: 300,
width: '100%'
});
var callback = function(data) {
movieValues[data.title] = true;
myConfig.scaleX.values = Object.keys(movieValues);
zingchart.exec('myChart', 'setdata', {
data:myConfig
})
}
var index = 0;
var movieNamesFromDB = ['Sausage Party', 'Animal House', 'Hot Rod', 'Blazing Saddles'];
setInterval(function() {
if (index < 4) {
callback({title:movieNamesFromDB[index++]});
}
},1000)
<!DOCTYPE html>
<html>
<head>
<!--Assets will be injected here on compile. Use the assets button above-->
<script src= "https://cdn.zingchart.com/zingchart.min.js"></script>
<script> zingchart.MODULESDIR = "https://cdn.zingchart.com/modules/";
</script>
<!--Inject End-->
</head>
<body>
<div id='myChart'></div>
</body>
</html>
If you noticed in the demo, the length of scaleX.values determines how many nodes are shown on the graph. If you change values to labels this wont happen.
Related
I'm using web component and OpenAPI. and my web component works by valuable [options]'s data.
it's a pie chart and divided by DATA_VALUE's value and ITEM_NAME is label to show!
I extract data from OpenAPI and want to add to array of [data] in var options.
I need to use rows[1] to [11] but now I'm using only rows[1] and it work's well.
so now i'm trying to do for statement rows[1] to [11]!
I'm wondering how can i add rows[1] to [11]'s data to [data] in var options?
i tried like this but it occurs error. guess it isn't on right location or wrong .
options.data.push({DATA_VALUE: dataV, ITEM_NAME2: itemNm2});
this is entire code.
<body>
<div class='pie'></div>
<script>
var styles = {
legend: {
use: true,
stackedGap: 5,
type: 'insideLegend',
text: {
family: 'Nanum Gothic',
size: 17,
color: '#333333',
style: 'normal', /* normal | italic */
weight: 'bold', /* normal | bold */
opacity: 1
}
}
};
$.ajax({
url: 'http://openapi.crimestats.or.kr/WiseOpen/PoliceDataList/ZTEADTY42D1XJ9XPOZDG/json/1/15/2016/22/01010000006/?/',
type: 'GET',
dataType: 'json',
success: function (resp) {
console.log(resp);
var rows = resp.PoliceDataList.row;
if (rows) {
var representativeRow = rows[1],
/* statNm = representativeRow.STAT_NAME,
baseYear = representativeRow.BASE_YEAR,
itemNm1 = representativeRow.ITEM_NAME1;*/
itemNm2 = representativeRow.ITEM_NAME2;
dataV = representativeRow.DATA_VALUE;
console.log(itemNm2);
console.log(dataV);
/*
var dataArray = [];
$.each(rows, function (idx, row) {
var tmp = [];
tmp.push(row.ITEM_NAME2);
tmp.push(Number(row.DATA_VALUE));
dataArray.push(tmp);
});
console.log(dataArray);
var jsonEncode = JSON.stringify(dataArray);
console.log(jsonEncode);*/
var options = {
data: {
data: [
{DATA_VALUE: dataV, ITEM_NAME2: itemNm2}
]
,
use: 'DATA_VALUE'
},
legend: {
use: 'ITEM_NAME2'
}
};
options.data.push({DATA_VALUE: dataV, ITEM_NAME2: itemNm2});
pie = webponent.visual.pie.init($(".pie"), styles, options);
}
}
});
</script>
</body>
this is example value of OpenAPI
{
"PoliceDataList":{
"list_total_count":12,
"row":[
{
"ITEM_NAME1":"강간",
"ITEM_NAME2":"계",
"ITEM_CODE2":"X0001",
"ITEM_CODE1":"01010000006",
"STAT_NAME":"검거자",
"DATA_VALUE":"5916",
"STAT_CODE":"22",
"BASE_YEAR":"2016"
},
{
"ITEM_NAME1":"강간",
"ITEM_NAME2":"수사·형사",
"ITEM_CODE2":"X0003",
"ITEM_CODE1":"01010000006",
"STAT_NAME":"검거자",
"DATA_VALUE":"979",
"STAT_CODE":"22",
"BASE_YEAR":"2016"
},
{
"ITEM_NAME1":"강간",
"ITEM_NAME2":"외근·112차",
"ITEM_CODE2":"X0004",
"ITEM_CODE1":"01010000006",
"STAT_NAME":"검거자",
"DATA_VALUE":"1032",
"STAT_CODE":"22",
"BASE_YEAR":"2016"
},
options.data.data.push({DTA_VAL: dataV, ITM_NM: itemNm2});
this works well!
I am trying to make some charts with custom data in jsreport and using Chart.js, the problem is that i don't know how to use custom data to fill my chart with. So far, i created a very big json with my data and the function to generate the chart and place inside a canvas, but i can't call the function inside my html with the handlebars because it says the document is not defined. So, how can i use my data to create my charts and display it inside a canvas?
P.S.: I can easily display a chart with static data, but i really want to do this using the json that i created.
My function to create my chart:
function graficoEstiloAdaptado(exame){
var ctx = document.getElementById('graficoEsquerdo').getContext('2d');
var total = 280;
var incentivador = 0;
var idealizador = 0;
var detalhista = 0;
var sociavel = 0;
for(var i=0;i<exame.respostas.length;i++){
for(var j=0;j<exame.respostas[i].alternativas.length;j++){
switch(exame.respostas[i].alternativas[j].categoria){
case 'Incentivador':
incentivador += 4-j;
break;
case 'Idealizador':
idealizador += 4-j;
break;
case 'Detalhista':
detalhista += 4-j;
break;
case 'Sociável':
sociavel += 4-j;
break;
}
}
}
var porcentagens = {
incentivador: (incentivador/total).toFixed(1),
idealizador: (idealizador/total).toFixed(1),
detalhista: (detalhista/total).toFixed(1),
sociavel: (sociavel/total).toFixed(1)
};
var chartEstiloAdaptado = new Chart(ctx, {
type: 'bar',
data: {
labels: [porcentagens.incentivador + "%", porcentagens.idealizador + "%", porcentagens.detalhista + "%", porcentagens.sociavel + "%"],
datasets: [{
label: "Gráfico I",
data: [
porcentagens.incentivador,
porcentagens.idealizador,
porcentagens.detalhista,
porcentagens.sociavel
]
}]
},
options: {
animation: {
onComplete: function() {
window.JSREPORT_READY_TO_START = true;
}
}
}
});
}
And i don't want to use an API to get the data yet, i just want to structure the report the way i like and after that use an API to fetch the data.
The main idea is described in this blog:
Define helper function which makes JSON string from the parameter
function toJSON(data) {
return JSON.stringify(data);
}
And call this helper in inline script
<script>
var data= {{{toJSON this}}}
</script>
The full example with chart.js can look like this
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js'></script>
</head>
<body>
<canvas id='myChart' style="margin-top:30px"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
datasets: [{
label: 'apples',
data: {{{toJSON A}}},
backgroundColor: "rgba(153,255,51,0.4)"
}, {
label: 'oranges',
data: {{{toJSON B}}},
backgroundColor: "rgba(255,153,0,0.4)"
}]
},
options: {
animation: {
onComplete: function () {
// set the PDF printing trigger when the animation is done
// to have this working, the phantom-pdf menu in the left must
// have the wait for printing trigger option selected
window.JSREPORT_READY_TO_START = true
}
}
}
});
</script>
</body>
</html>
Working playground demo can be found here.
My requirement is to display the bar graph.I'm using angularjs and Zingchart to display the bar. Belowis the javascript code which gets invoked to generate the bar. I'm facing issue in iterating the logic(angular.forEach..) in the below mentioned code.
My alert statement inside angular.forEach is displayed 3 times, but on the UI i can only see one bar displayed(i.e.,bar with final data is displayed, first two bars are not getting displayed).
I know i'm missing something which draws each and every bar instead of the last displayed bar. Do i need to use any push statemetns. Please advice.
app.controller('myController',['$rootScope','$scope','$uibModal','myService',function($rootScope,$scope,$uibModal,myService) {
$scope.chart = {};
$scope.chart.options = {
"isStacked": "true",
axisFontSize : 10,
chartArea: {left:0, width: 400,}
};
$scope.chart.type = "bar";
$scope.chart.cssStyle = "height:300px; width:650px;";
$scope.loadChartData = function(){
alert("Chart data loading");
MyService.getChartData($rootScope.myID).then(
function(response) {
$scope.myJson=response;
angular.forEach($scope.myJson,function(value,key){
alert("in foreach"); //displaying 3 times
sub = value.myResults.sub;
spread = value.myResults.spread;
active =value.myResults.active;
$scope.data = {};
$scope.data.valuesOne = [sub];
$scope.data.valuesTwo = [spread];
$scope.data.valuesThree = [active];
$scope.aValues = [$scope.data.valuesOne,$scope.data.valuesTwo,$scope.data.valuesThree];
$scope.myJson = {
type : "bar",
"background-color": "white",
"plot": {
"stacked": true,
"stack-type":"normal"
},
title:{
backgroundColor : "transparent",
fontColor :"black",
text : "Hello world"
},
backgroundColor : "white",
series : [
{
backgroundColor : '#00baf2'
},
{
backgroundColor : '#4caf4f'
}
]
};
});
},
function(errResponse){
console.error('Error while data retrieval');
});
}
}]);
html code:
<div ng-controller="myController">
<div zingchart id="chart-2" zc-json="myJson" zc-width="700px" zc-height="568px" zc-values="aValues"></div>
</div>
With the above mentioned js code i should see 3 bars on the UI, i could able to view only one bar.Please suggest.
You need to call foreach on the data, rather than the whole chart. Like this:
...
function(response) {
$scope.myJson = {
type: "bar",
"background-color": "white",
"plot": {
"stacked": true,
"stack-type": "normal"
},
title: {
backgroundColor: "transparent",
fontColor: "black",
text: "Hello world"
},
backgroundColor: "white",
series: [
{
backgroundColor: '#00baf2'
},
{
backgroundColor: '#4caf4f'
}
]
};
var subs = []
var spreads = []
var actives = []
$scope.aValues = [subs, spreads, actives]
angular.forEach(response, function (value, key) {
subs.push(value.myResults.sub)
spreads.push(value.myResults.spreads)
actives.push(value.myResults.active)
});
},
function(errResponse) {
console.error('Error while data retrieval');
});
...
There are a few things I have to add:
1. Zingchart Syntax
Did you already have a look at these docs: https://www.zingchart.com/docs/chart-types/bar-charts/
It says, the bar chart needs a series object as input with the following structure:
"series": [
{"values":[20,40,25,50,15,45,33,34]},
{"values":[5,30,21,18,59,50,28,33]},
{"values":[30,5,18,21,33,41,29,15]}
]
Is it a must to feed the chart from HTML? Otherwise you just could copy the JS example from the link above.
IMHO this is much cleaner, as you do not push that much data in the scope.
2. Overwriting myJson
Something looks a little wrong with the forEach loop.
There is a angular.forEach that should iterate over the array $scope.myJson. But inside the iterator function, $scope.myJson gets overwrtitten by an object.
3. ng-repeat
ng-repeat will only repeat the chart tag. You need to pass several series to the directive.
Although I've specified text and hoverinfo, I'm not getting any hover annotation at all.
If I comment out the "text" attribute, I get the default behavior of hoverinfo: "x+y". I've also tried hoverinfo: "text" and hoverinfo: "x+text" (which is what I really want), but these do not change the behavior.
https://jsfiddle.net/abalter/0cjprqgy/
var data =
{
"x":["2014-02-10 00:00:00.0","2014-02-18 00:00:00.0","2014-02-24 00:00:00.0"],
"y":[0,0,0],
"text":["gemcitabine","gemcitabine + Abraxane","Xeloda"],
"hoverinfo": "all",
"name":"Treatment",
"type":"scatter",
"mode":"markers",
"marker":
{
"size":9,
"color":"#800000"
},
"uid":"c2e171"
};
var layout =
{
"title":"Treatments",
"height":600,
"width":655,
"autosize":true,
"yaxis":
{
"titlefont":
{
"size":12,
"color":"#800000"
},
"domain":[0.85,0.9],
"showgrid":false,
"showline":false,
"showticklabels":false,
"zeroline":true,
"type":"linear",
"range":[0,0],
"autorange":true
},
"hovermode":"closest",
"xaxis":
{
"type":"date",
"range":[1389215256994.8186,1434909143005.1814],
"autorange":true
}
};
Plotly.plot('graph', [data], layout);
First of all, thank you for having me to discover this really cool graphic platform! I checked at the documentation to get to know how the data has to be formatted (here: https://plot.ly/javascript/hover-events/#coupled-hover-events-on-single-plot)... And "played" with you fiddle.
First, I removed all the unnessessary double quotes you had there, wrapping the param names and placed your value arrays outside of the "data" array. I don't know if it is part of the problem... I just tryed to format it as the example I found.
The "x+y+text" suddenly appeared when I played with the "domain" parameter.
I don't know what it really defines.
I repeat, I have a 10 minutes experience with this thing. (lol)
Check this update I made of your fiddle : https://jsfiddle.net/0cjprqgy/6/
var dates = ["2014-02-10 00:00:00.0","2014-02-18 00:00:00.0","2014-02-24 00:00:00.0"],
qty = ["0.2","0.5","1"],
product = ["gemcitabine","gemcitabine + Abraxane","Xeloda"],
data =
{
x:dates,
y:qty,
text:product,
hoverinfo: "x+y+text",
name:"Treatment",
type:"scatter",
mode:"markers",
marker:
{
size:9,
color:"#800000"
},
uid:"c2e171"
};
var layout =
{
title:"Treatments",
height:600,
width:655,
autosize:true,
yaxis:
{
titlefont:
{
size:12,
color:"#800000"
},
domain:[0.85,1.9],
showgrid:false,
showline:false,
showticklabels:false,
zeroline:true,
type:"linear",
range:[0,0],
autorange:true
},
hovermode:"closest",
xaxis:
{
type:"date",
range:[1389215256994.8186,1434909143005.1814],
autorange:true
}
};
Plotly.plot('graph', [data], layout);
jTable (jTable.org) layout is defined by the code below. I want to build it dynamically (based on AJAX return from a database query).
{
title: 'My Dynamic Title',
fields: {
id: {
title: 'ID'
},
salesperson: {
title: 'Salesperson'
},
pivot1: {
title: '2012-01'
},
pivot2: {
title: '2012-02'
},
pivot3: {
title: '2012-03'
}
}
}
The data being displayed is a pivot table and so the number of columns and their titles will change. Is it possible for me to dynamically modify the fields section above? e.g., to have four pivot columns with relevant column titles.
Answer
I figured it out thanks to Barmar and extensive reading. The trick is to insert a new object at each level. Pop this into jsfiddle.net and you can see the result. It will programmatically create the object above.
var myobj = {}; //description for jquery-jtable configuration.
var colnames = ['pivot1', 'pivot2', 'pivot3'];
var titles = ['2012-01', '2012-02', '2012-03'];
myobj['title'] = "My Dynamic Title";
myobj['fields'] = {}; //create a second level under 'fields'.
myobj.fields['id'] = {title: 'ID'};
myobj.fields['salesperson'] = {title: 'Salesperson'};
for(i = 0; i < colnames.length; i++) {
myobj.fields[colnames[i]] = {}; //create a third level under column name.
myobj.fields[colnames[i]].title = titles[i];
}
alert(JSON.stringify(myobj, null, 4));
I don't see a method to change the field specification dynamically. But if you're modifying the table, you can simply destroy the old jTable and reinitialize it:
$("#TableContainer").jtable("destroy");
$("#TableContainer").jtable({
// New options
});
If there are some options that will stay consistent across all instances, you can use a variable to hold the options:
var jtable_options = {
title: "My Table Title",
fields: {}
};
Before you initialize a jtable, you do:
jtable_options.fields = {
id: { title: 'ID' },
salesperson: { title: 'Salesperson' }
...
};
$("#TableContainer").jtable(jtable_options);