duplicate month data into stack in morris bar chart - javascript

how to push data into stack of morris bar chart, if come multiple similar month data from ajax call from different account
this is my code:
DashboardService.getGraphForYear(year).success(function (data) {
$scope.count = data.results_count;
for(var j=0;j< $scope.count;j++)
{
$scope.month = data.results[j].month;
switch ($scope.month) {
case 1:
sales_com_year.push({month:month[1],amount:data.results[j].order_total_amount});
break;
case 2: sales_com_year.push({month:month[2],amount:data.results[j].order_total_amount});
break;
}
}
}).error(function (error) });
How to push data into if come January so all data push into as a stack into January as well for all month

You have to create list that have date and value pair push into an array
var myJSON = [];
$.each(YourList, function (i, item) {
var jsonArray = { year: item.Date, value: item.value };
var temp = jsonArray;
myJSON.push(temp);
});
and internalize Morris.Area with following parameters.
Morris.Area({
element: 'chart',
xLabelMargin: 10,
xLabelAngle: 60,
parseTime: false,
data: myJSON,
xkey: 'year',
ykeys: ['value'],
labels: ['Your Lable'],
lineColors: ['red'],
pointFillColors: ['#ffffff'],
pointStrokeColors: ['black'],
});

Related

Storing Highcharts in array issue

I am plotting a number of highcharts dynamically in a loop and pushing each highchart to an array. So that while clicking on an external button, I can export the charts. But while pushing charts to array, only the last entry is properly set with options.
i had a reference to a fiddle that suggests to clone the options. [https://jsfiddle.net/ndb21y1w/][2]
https://www.highcharts.com/forum/viewtopic.php?t=38574
The fiddle have same series data plotted on all the charts. How to solve this if the data is different for each chart populated. Thanks for any help in advance.
Adding more clarity to question :
The data is populated dynamically in loop. My code logic is like:
counter i;
setInterval(function() {
//logic to populated data...
//It is a multiline chart, so three sets of arrays are populated.
//filling data1[], data2[] and data3[] .
drawChart(data1, data2, data3);
if(condition true) clearInterval();
i++;
});
drawChart(data1, data2, data3) {
var chart = new Highcharts.Chart({
title: {
text: "title",
},
xAxis: {
categories: [1,2,3,4...],
},
series: [{
type: 'line',
data: data1,
}, {
type: 'line',
data: data2,
}, {
type: 'line',
data: data3,
},
});
chartArray.push(chart);
}
This chartArray is where I mentioned to get the last entry only properly.
To create a chart you have to pass an HTML element that will be a chart container. In your code that what's missing. Check the demo I have prepared to reproduce this issue: https://jsfiddle.net/BlackLabel/c60y1t2v/
Code:
var chartArray = [],
counter = 1,
dataArr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
containers = document.getElementById('containers');
function drawChart(data) {
var cnt = document.createElement('div'),
cntId = 'container' + counter++,
chart;
cnt.setAttribute('id', cntId);
containers.appendChild(cnt);
chart = new Highcharts.Chart(cntId, {
title: {
text: "title",
},
xAxis: {
categories: [1, 2, 3, 4],
},
series: [{
type: 'line',
data: data,
}]
});
return chart;
}
dataArr.forEach(function(data) {
var chart = drawChart(data);
chartArray.push(chart);
});
You need to define options each time you use a new chart. Reinitialize the OriginalOptions every time you create a new chart.
const options = [...Array(5)].map(() => {
const originalOptions = {
series: [{
data: [], // some random data
type: 'column'
}]
}
return Object.assign(originalOptions)
})
Fiddle
Updated:
For dynamically repopulating the chart, you have to initialize an empty chart and then add new series + redraw whenever your data is populated.
Your redraw function will look something like this:
var i = 0;
var data = [];
var chart = new Highcharts.Chart('container',{
series: []
});
var interval = setInterval(function() {
i++;
data[i] = [i*10 + 1, i*10+2, i*10+3];
drawChart(data[i]);
if(i > 2) clearInterval(interval);
},1000);
function drawChart(data) {
var series = {
type: 'line',
data: data
}
chart.addSeries(series, false);
chart.redraw();
}
See Updated Fiddle
To Print HTML as PDF you can use this software "wkhtmltopdf"
in Linux you need to use this command :
sudo apt-get install wkhtmltopdf
There are many library based on "wkhtmltopdf" in many languages so you can use it.
Library for PHP : https://github.com/mikehaertl/phpwkhtmltopdf
Store chart options in Array then map over to Initialize Highchart for each options.
var chartArray = [];
function drawChart(data1, data2, data3, i) {
// Create container for charts
const el = document.createElement('div');
document.body.appendChild(el).setAttribute("id", "container"+i);
// Create charts
var chart = new Highcharts.chart(el, {
series: [{
type: 'line',
data: data1,
}, {
type: 'line',
data: data2,
}, {
type: 'line',
data: data3,
}]
});
chartArray.push(chart);
console.log(chartArray);
}
var counter = 0;
var delayTime = 2000;
var timer = setInterval(function(){
var data1 = [30, 70, 50];
var data2 = [40, 70, 60];
var data3 = [10, 90, 20];
drawChart(data1, data2, data3, counter);
if(counter == 2){
clearInterval(timer);
}
counter++;
},delayTime);
<script src="https://code.highcharts.com/highcharts.js"></script>

is it possible to have 2 data sets on single line chart in chart.js?

Preview:
I am using chart.js in Angular 7 application. I want to know, is it possible to have 2 data sets on single line chart.
Detail:
On my X-axis I have time related data and Y-axis contains numbers. Based on API response, (which returns time stamp and number) I can generate a line chart. But I want to have 2nd datasets on same line. 2nd data set related API response, gives me time stamp, so I want to use that time stamp to project point (maybe of different color) to show on single line.
this.chart = new Chart(ctx, {
type: 'line',
data: this.getChartAxisData(),
options: this.getChartOptions()
});
getChartAxisData() {
const first: any[] = this.listOne.map((data) => (new Date(data.date)));
const firstArray: any[] = this.listOne.map((data) => data.number);
const second: any[] = this.listTwo.map((data) => (new Date(data.date)));
return {
labels: first,
datasets: [
{
data: firstArray
}
]
};
}
getChartOptions() {
return {
scales: {
xAxes: [{
type: 'time',
time: {
max: this.endDate,
min: this.startDate,
displayFormats: {
'millisecond': 'hh:mm A',
'second': 'hh:mm A',
'minute': 'hh:mm A',
'hour': 'hh:mm A',
'day': 'DD-MMM',
'week': 'DD-MMM',
'month': 'DD-MMM'
}
}
}],
yAxes: [{
ticks: {
min: 0,
max: 800
}
}]
}
};
}

howto use vaxis in google charts materialview

I have been fiddling with a particle photon, posting data to sparkfun.com
To display this data I am trying to use google.visualization. But I cant seem to get the axis behaving as I want it to.
see (but wait a while it is slow): https://www.hanscees.com/photon/charts-data-sparkfunA.html
I want the caxis to show not 1K, but 1010 and so on. here is my code:
function drawChart1() {
var public_key = 'yA0EjKV3owhKNx1NlN3w';
// JSONP request
var jsonData = $.ajax({
url: 'https://data.sparkfun.com/output/' + public_key + '.json',
//data: {page: 1},
data: {'lte' : {'timestamp' : 'now - 4 hours'}},
dataType: 'jsonp',
}).done(function (results) {
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Pressure');
$.each(results, function (i, row) {
data.addRow([
(new Date(row.timestamp)),
parseFloat(row.hectopascals)
]);
}); // each row
// see https://google-developers.appspot.com/chart/interactive/docs/gallery/linechart#dual-y-charts
var materialOptions = {
chart: { title: 'Barometer Pressure'},
width: 550,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: {axis: 'Pressure'}
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Pressure: {label: 'Pressure (Hpa)'}
}
},
vAxis: {format: 'decimal'},
hAxis: {color: '#333', count: 8}
};
var materialChart = new google.charts.Line(ChartDivBaro);
materialChart.draw(data, materialOptions);
}); // results
} // jsondata
unfortunately, most vAxis options simply do not work on material charts...
see --> Tracking Issue for Material Chart Feature Parity #2143
recommend using a core chart instead...
you can use the following option to get the look and feel close to material
theme: 'material'
solved it without material:
var options = {title:'Pressure Outside',
width:550,
height:300,
vAxis: {format: '0'}
};
var chart = new google.visualization.LineChart($('#chart1').get(0));
chart.draw(data, options); // draw data
}); // results

Google Charts stopped working - Uncaught Error: Row 14 has 2 columns, but must have 4

EDIT: It seems some of my raw data does not contain a value for each of the three stacked bars. This is valid and based on user choice. Example: a restaurant may have a breakfast only menu, but no Sandwiches or Light Meals (see below).
The Google Chart is falling over at this row, where there are no physical entries of ZERO for the (valid) missing user selections.
Is there a Google Charts setting whereby a "missing value" is treated as ZERO value?
Here's an example of the JSON input:
[{"store_name":"Store 1","dish_menu":"Breakfast","dish_count":"13"},
{"store_name":"Store 1","dish_menu":"Light Meals","dish_count":"7"},
{"store_name":"Store 1","dish_menu":"Sandwiches","dish_count":"7"},
{"store_name":"Store 2","dish_menu":"Breakfast","dish_count":"13"},
{"store_name":"Store 2","dish_menu":"Light Meals","dish_count":"7"},
{"store_name":"Store 2","dish_menu":"Sandwiches","dish_count":"7"},
{"store_name":"Store 3","dish_menu":"Breakfast","dish_count":"13"}, <-- FAILS HERE
{"store_name":"Store 4","dish_menu":"Breakfast","dish_count":"13"},
{"store_name":"Store 4","dish_menu":"Light Meals","dish_count":"7"},
{"store_name":"Store 4","dish_menu":"Sandwiches","dish_count":"7"},]
I have 3 Google charts on a page, 2 are pie, 1 is a stacked bar.
Today, for reasons I cannot understand, the stacked bar chart stopped working and the message inspect shows is "Error: Row 14 has 2 columns, but must have 4", and points to the bowels of Google code. This page has been in production for over a month and working just fine.
When I look at the code and compare it with last back up (which was was working OK, 2 weeks old), the code is exactly the same. Also, the SQL query output is working just fine.
Any suggestions on where to look are highly appreciated.
CODE:
function loadHQCharts() {
// CHART #1
google.load('visualization', '1', {'packages':['corechart'], callback: drawChartDishMix});
// CHART #2
google.load('visualization', '1', {'packages':['corechart'], callback: drawChartMenuMix});
// CHART #3
google.load('visualization', '1', {'packages':['corechart'], callback: drawChartStoreMix});
};
function drawChartStoreMix() {
var url = window.location.origin + '/tce-php/getdata.php?var=HQLOADMMS';
jQuery.getJSON( url, function(json) {
// convert JSON to chart required format
var stores = _.chain(json).pluck("store_name").sort().uniq(true).value();
var tempHTML = "";
jQuery('#store_list').empty();
stores.forEach(function (entry) {
tempHTML = tempHTML + '<option value="' + entry + '">' + entry + '</option>';
});
/*** Load data into drop down lists here ***/
var store_selector = document.getElementById('store_list');
store_selector.insertAdjacentHTML('beforeend', tempHTML);
/*** Load default selections for top of drop down lists here ***/
store_selector.insertAdjacentHTML('afterbegin', '<option selected="selected" value="ALL">All Stores...</option>');
var header = _.chain(json).pluck("dish_menu").sort().uniq(true).value();
header.unshift("Menus");
var rows = _.chain(json)
.groupBy(function(item) { return item.store_name; })
.map(function(group, key) {
var result = [key];
_.each(group, function(item) {
result[_.indexOf(header, item.dish_menu)] = parseInt(item.dish_count);
});
return result;
})
.value();
var jsonData = [header].concat(rows);
var data = google.visualization.arrayToDataTable(jsonData);
// Set chart options
var options = {
title: 'Menu Mix By Store',
titleTextStyle:{ color:'#747474', fontSize:'15', bold:false },
isStacked: true,
chartArea: { left: '55', top: '50', width: '88%', height: '65%' },
is3D: true,
legend: { position:'top'},
legendTextStyle: { color:'#747474', fontSize:'11', bold:false },
bar: { groupWidth: '75%' },
vAxis:{ title:'', textStyle:{color: '#747474',fontSize: '11', paddingRight: '0',marginRight: '0'} },
hAxis: { title: '', textStyle: { color: '#747474', fontSize: '11', paddingRight: '0', marginRight: '0'} }
// vAxis: {title: '# Dishes'},
// hAxis: {title: 'Stores'}
// legend: {position: 'none'},
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.ColumnChart(document.getElementById('fran_mix'));
chart.draw(data, options);
})
.done(function() {
})
.fail(function() {
});
};
JSON sample:
[{"store_name":"Store 1","dish_menu":"Breakfast","dish_count":"13"},
{"store_name":"Store 1","dish_menu":"Light Meals","dish_count":"7"},
{"store_name":"Store 1","dish_menu":"Sandwiches","dish_count":"7"},...]
The problem is not that the Visualization API doesn't know what to do with the missing values, it's that you aren't providing the complete structure to the DataTable constructor. Your jsonData variable contains an array like this:
[
['Menus', 'Breakfast', 'Light Meals', 'Sandwiches']
['Store 1', 13, 7, 7],
['Store 2', 13, 7, 7],
['Store 3', 13],
['Store 4', 13, 7, 7]
]
The constructor requires that each row have the same number of columns as the DataTable (as defined by the header row, in this case). If you replace this line:
var result = [key];
with these:
var result = new Array(header.length).map(function () {return null;});
result[0] = key;
your arrays will all be the proper length, with nulls filled in where you don't have any values. The chart should draw fine with this.
For the API loading, replace the three calls to google.load with a single call:
google.load('visualization', '1', {'packages':['corechart'], callback: function () {
drawChartDishMix();
drawChartMenuMix();
drawChartStoreMix();
}});

Highcharts: Plot yAxis values starting from a specific range

I am using highstocks and I am wondering if there is anyway I can plot the y values in a column series starting from an arbitrary number. For example. I have a column series called NU (New Users) with its first entry yAxis value of 1,000. Currently, that first entry is plotted on the yAxis from range [0, 1,000]. But instead I would like it to be plotted from [5,000, 6,000].
The reason I want this is because NU is essentially apart of another column called DAU (Daily Active Users), and I want it to be shown up as so. The first entry of the DAU column series has a Y value of 6,000, and 6,000 - 1,000 is 5,000; therefore I would like this entry of NU to start at 5,000.
Here is what I have so far
http://jsfiddle.net/6JACr/2/
I was going to plot DAU as (Original DAU - NU), and stack NU on top of DAU, but that would mean the series holds an incorrect value for DAU.
Here is my code
$(document).ready(function() {
var all_series = [];
var accu_series;
var accu_data = [];
var pccu_series = [];
var pccu_data = [];
var dau_series;
var dau_data = [];
var nu_series;
var nu_data = [];
function draw_charts() {
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1,
buttons: [{
type: 'week',
count: 1,
text: '1w'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'month',
count: 3,
text: '3m'
}, {
type: 'month',
count: 6,
text: '6m'
}, {
type: 'ytd',
text: 'YTD'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}]
},
plotOptions: {
column: {
grouping: false
}
},
yAxis: [{
// Primary Y-Axis
labels:{
align:'right',
x:-10
},
lineWidth : 1,
offset : 0
}, {
// Secondary Y-Axis
opposite: true
}],
series : all_series
});
}
//Function that takes a record and fills the series data with that record
function fill_data(index, record) {
var date = new Date(record['dailyDate']);
var utc_date = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
accu_data[index] = [utc_date, parseFloat(record['accu'])];
dau_data[index] = [utc_date, parseFloat(record['dau'])];
nu_data[index] = [utc_date, parseFloat(record['users'])];
}
// //Function that sets up the series data for plotting
function fill_series() {
dau_series = {
name: "DAU",
type: "column",
data: dau_data,
stack: 0
};
all_series[0] = dau_series;
nu_series = {
name: "NU",
type: "column",
data: nu_data,
stack: 0
};
all_series[1] = nu_series;
}
//Pull data from API, format it, and store into the series arrays
(function() {
var result = '[{"accounts":"1668","accu":"568","activePayingRate":"1.97757","activePayingUsers":"854","activeUsers":"4905","area":"1","arpu":"34.6908","company":"45","dailyDate":"2013-08-06","dau":"6000","lost":"87","newUser":"0","paying":"96","payingRate":"1.53724","pccu":"747.0","registration":"572","sales":"3305.01","server":"1","users":"1000"},{"accounts":"1554","accu":"497","activePayingRate":"2.18398","activePayingUsers":"833","activeUsers":"4533","area":"1","arpu":"34.7479","company":"45","dailyDate":"2013-08-07","dau":"5873","lost":"89","newUser":"0","paying":"96","payingRate":"1.68568","pccu":"759.0","registration":"483","sales":"3300.04","server":"1","users":"1209"}]';
var json_result = JSON.parse(result);
$.each(json_result, function(index, record) {
fill_data(index,record);
});
fill_series();
draw_charts();
})();
});
You can use low property for column, for example: http://jsfiddle.net/6JACr/4/
To display proper tooltip, add extra property like val and use pointFormat to display it.
Note: when dataGrouping will be used custom properties are removed, in that case I advice to create your own tooltip formatter, to display what you need.

Categories

Resources