Morris Chart is Missing Half Part - javascript

I used morris chart in my application project to show some details about quantity of sales.
After executing the AJAX request, the chart is only showing half part. Here's the syntax:
var chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
//getting the morris chart over bahan and karakteristik
function getBahanPotensial(kode){
//ajax call
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateListBahanPotensial",
data:{
kode:kode
},
success: function(data){
chartBahan.setData($.parseJSON(data));
chartBahan.redraw();
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
var chartKarakter = new Morris.Bar ({
element: 'morris-analytics-karakter',
xkey: '2',
ykeys: ['3'],
labels: ['Karakter Quantity'],
resize: true
});
function getKarakterPotensial(kode){
//ajax call
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateListKarakterPotensial",
data:{
kode:kode
},
success:function(data){
chartKarakter.setData($.parseJSON(data));
chartKarakter.redraw();
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
I execute the above function from another function let say doProcess()
function sendRequest(thecode){
if(thecode === ""){ alert("Tolong Input Kode Produk");}
else {
var kodebarang = thecode;
}
//executing AJAX call.
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateAnalytics",
data:{
kodebarang:kodebarang
},
success:function(msg){
$('#result_analysis').show();
$('#navigation_button').show();
new Morris.Bar ({
element: 'morris-analytics-bar',
data: $.parseJSON(msg),
xkey: '1',
ykeys: ['2', '3'],
labels: ['Sales Area', 'Tingkat Penjualan'],
barRatio: 0.4,
xLabelAngle: 0,
hideHover: 'auto'
});
//execute the morris chart others !! PENTING
var kodeb = $('#bahan_id').val();
var kodek = $('#karakteristik_id').val();
getBahanPotensial(kodeb);
getKarakterPotensial(kodek);
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
but the problem is, when i create Morris Chart in Success Callback
success:function(msg){
$('#result_analysis').show();
$('#navigation_button').show();
new Morris.Bar ({
element: 'morris-analytics-bar',
data: $.parseJSON(msg),
xkey: '1',
ykeys: ['2', '3'],
labels: ['Sales Area', 'Tingkat Penjualan'],
barRatio: 0.4,
xLabelAngle: 0,
hideHover: 'auto'
});
The chart is properly showing. Here's the screen shot:
But the other chart when i use template for charting (outside the success callback) the chart is BROKEN
here's the screenshot
then, i have dropdown list to regenerate the chart based on specific parameter, the chart is properly showing (all data show) BUT the chart is only half PAGE. here's the screenshot:
Is there any ideas what going on?
UPDATE
What I mean template is code like this:
var chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
and the method to call the template is
success:function(data){
chartBahan.setData($.parseJSON(data));
chartBahan.redraw();
},
The RIGHT chart is the FIRST Screenshot. It's wider than the other two.
UPDATED 2
still getting error on charts created by Morris :(
here's the screenshot.

I solved that issue by setting the width of the svg element to 100% in css
svg{
width: 100% !important
}

Two last charts from your example threw lots of errors in the console of Google Chrome (you can open it by pressing F12).
The reason is that the data property is required when you call Morris.Bar({ data: ... }), but in you example you didn't have this property. So you should completely remove your declarations like var chartBahan = Morris.Bar (... and replace the success callback with this code:
function getBahanPotensial(kode){
$.ajax({
...
success: function(data){
if (window.chartBahan) {
chartBahan.setData($.parseJSON(data));
// chartBahan.redraw(); // useless call, it can be removed
} else {
window.chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
data: $.parseJSON(data),
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
}
}
...
});
}
In my code I check whether the global variable window.chartBahan exists and if it doesn't - I create a new chart; otherwise I call setData and the chart updates itself automatically.
Also you haven't posted your HTML mark-up, it may have issues as well. I used this HTML code and it worked fine:
<body>
<div id="morris-analytics-bar" style="height: 250px;"></div>
<div id="morris-analytics-bahan" style="height: 250px;"></div>
<div id="morris-analytics-karakter" style="height: 250px;"></div>
</body>

//Java script code
Morris.Line({
element: 'hero-area',
data: getdata("<?php echo base_url('user/getYearlPremiumuser');?>") ,
xkey: 'Year',
parseTime: false,
ykeys: ['Teacher', 'Student'],
labels: ['Teacher', 'Student'],
hideHover: 'false',
lineWidth: 1,
pointSize: 5,
lineColors: ['#4a8bc2', '#ff6c60'],
fillOpacity:7,
smooth: true
});
********//php code ( code codeigniter)********
public function getYearlPremiumuser()
{
$teacherArray={ y: '2014', a: 50, b: 90},
{ y: '2015', a: 65, b: 75},
{ y: '2016', a: 50, b: 50},
{ y: '2017', a: 75, b: 60},
{ y: '2018', a: 80, b: 65},
{ y: '2019', a: 90, b: 70},
{ y: '2020', a: 100, b: 75},
{ y: '2021', a: 115, b: 75},
{ y: '2022', a: 120, b: 85},
{ y: '2023', a: 145, b: 85},
{ y: '2024', a: 160, b: 95}
for($i=0;$i<count($teacherArray);$i++)
{
$temp=array();
$temp= array_merge($teacherArray[$i],$studentarray[$i]);
$finalResultArray[]=$temp;
}
echo json_encode($finalResultArray);
}
click here to know more

I have similar issue using Morris.js and Angular2 - the problem in my case was that I use in DIV with chart the *ngIf='showChart' (or [hidden]='!showChart') - and when I set up chart, the showChar=false so the div doesn't exist. In my case I read date periodic in every 1min so at first dataLoad i see nothing, after second dataLoad i see half/part of chart). So I fix this by (typescript):
showchart = true;
setTimeout( () => { this.setUpChart() }, 1 );
And it works :)

Related

Form data series for highcharts columns

From the official documentation I can't get if it is possible for me to build a chart in the way I want.
Simple example of the initial data:
{
'Player1': {'item1': '50'},
'Player2': {'item1': '60', 'item2': '20'},
'Player3': {'item3': '40'}
}
It is like the 3 dimensions: Players/Items/Values.
I would like to build a chart with the column type.
X-Axis for the PlayerNames and Y-Axis for the Values.
The Items might be like the series-names so I can select them one by one and switch their visible option.
The issues - is that I don't get how to properly build the series and is that possible to bind their values between X-Y:
series: [{
name: 'item1',
data: [{x: 'Player1', y: 50}, {x: 'Player2', y: 60}],
visible: false
},
{
name: 'item2',
data: [{x: 'Player2', y: 20}],
visible: false
},
{
name: 'item3',
data: [{x: 'Player3', y: 40}],
visible: false
}
]
This would let me to show on the X-Axis only the colums that actually have the data. Without the empty space.
Can I achieve this somehow?
Thanks!
I was lucky to find the way how to do it:
First of all I should mention that x works only for the numbers:
x: number
Here is the way how to do it for string values:
xAxis: {
type: 'category',
},
And then just as:
series: [
{
name: 'item1',
data: [['Player1', 50], ['Player2', 75]],
visible: true
},
{
name: 'item2',
data: [['Player1', 25], ['Player3', 60], ['Player4', 40]],
visible: false
}
],

Iterating through array in Chart.js data field

Update:
var voltagedata1 = [];
batterybank1.forEach(function(element){
var voltage = {x: element.timestamp, y:element.voltage};
voltagedata1.push(voltage);
})
data: voltagedata1
I have an array which I want to iterate through in the data field of the Chart.js chart.
This code works for example:
data: [
{x: '2019-08-12 09:40:15', y:4}, {x: '2019-08-13 09:40:15', y:5}, {x: '2019-08-14 09:40:15', y:6},
],
Then trying to iterate through the array as follows:
batterybank1.forEach(function(element){
console.log(element)
"{x:\'element.timestamp', y:element.voltage},"
})
The console.log(element) gives a correct output, however the chart is not getting updated... on the console I am getting no warnings/errors - just the graph does not output.
The following does not work either, only the console.log is outputted but the graph is not updated.
batterybank1.forEach(function(element){
console.log(element)
"{x:\'2019-08-12 09:40:15', 1},"
})
It's explained in the documentation, that you add your points to the chart one at a time, like so:
batterybank1.forEach(function(element){
chart.data.datasets[0].data.push(element);
})
This is assuming that element is in the same format as the points in data.
After that you need to call chart.update(); to show the new data.
below is a working example:
let data = [{t: '2019-08-12 09:40:15', y:4}, {t: '2019-08-13 09:40:15', y:5}, {t: '2019-08-14 09:40:15', y:6}, {t: '2019-08-15 09:40:15', y:7}];
var chart = new Chart(document.getElementById('cht'), { type:'bar', data:
{
datasets:[{
label: 'CHRT - Chart.js Corporation',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
type: 'bar',
pointRadius: 0,
fill: false,
lineTension: 0,
borderWidth: 2,
data: data}]
}, options:{
scales: {
xAxes: [
{
type: 'time',
distribution: 'series',
ticks:
{
source: 'data',
autoSkip: true
}
}]
}
} });
document.getElementById('addPoints').addEventListener('click', function() {
let extra = [{t: '2019-08-16 09:40:15', y:4}, {t: '2019-08-17 09:40:15', y:5}, {t: '2019-08-18 09:40:15', y:6}, {t: '2019-08-19 09:40:15', y:7}];
extra.forEach(p =>
{
chart.data.datasets[0].data.push(p);
});
chart.update();
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>
<button id="addPoints">Add Points</button>
<canvas id="cht" class="chartjs" width="770" height="385" style="display: block; width: 770px; height: 385px;">

Replace chart code of data-ui-options attribute

I'm new with this and I'd like to know how can I replace the chart code into attribute data-ui-options unsing JQUERY.
<div id="graficoHell" data-ui-jp="echarts" data-ui-options="{
xAxis: {
data: ['a', 'b', 'c', 'd'],
axisTick: {show: false},
axisLabel: {
formatter: 'barGap: \'-100%\''
}
},
yAxis: {
splitLine: {show: false}
},
animationDurationUpdate: 1200,
series: [{
type: 'bar',
itemStyle: {
normal: {
color: '#ddd'
}
},
silent: true,
barWidth: 40,
barGap: '-100%', // Make series be overlap
data: [60, 60, 60, 60]
}, {
type: 'bar',
barWidth: 40,
z: 10,
data: [4, 60, 13, 25]
}]
} " style="height:300px" >
I tried the same code as string into JavaScript but it did not work.
$('#graficoHell').attr('data-ui-options', "same_string_into_data-ui-options");
All examples I saw, was using echarts object, but the template I bought is in this way.
Even though this is an old question I may answer it anyway.
You can use the element.dataset function in order to query / change data of an html element.
Querying the data according to the documentation:
<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>John Doe</div>
const el = document.querySelector('#user');
// el.id == 'user'
// el.dataset.id === '1234567890'
// el.dataset.user === 'johndoe'
// el.dataset.dateOfBirth === ''
Updating data:
const el = document.querySelector('#user');
el.dataset.dateOfBirth = '1960-10-03';

Show a "Bar" for zero results with morris.js

I'm using Morris.js to display data in charts, Id like to show a bar for every option, even if its zero, currently I get this:
As you can see the values for 'HIV Instant' for age group 21-25 and 26-30 are 0, how would I show a line (just a thin one) for each result? is this possible with Morris? I've searched the docs for bar charts & searched google & SO but cant find anything? Any help is appreciated. Cheers
Here is the code for generating said chart:
// break up the object
var age_barParts = [];
$.each( results_by_age_chart, function(key , val){
age_barParts.push({
'test': key,
'u16': val['u16'],
'16-20': val['16-20'],
'21-25': val['21-25'],
'26-30': val['26-30'],
'31-49': val['31-49'],
'50+': val['50+']
});
});
//build the graph
var age_bar = Morris.Bar({
element: 'age_bar',
data: age_barParts,
xkey: ['test'],
ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
barColors: color_array,
hideHover: 'auto',
resize: 'true',
gridTextSize: 16,
gridTextColor: '#5cb85c',
xLabelAngle: '70',
resize: true,
padding: 40
});
In Morris.js there is no option to force drawing of a line for zero values, but you can set them to a very low non-zero value, for example 0.05.
Below an example with Morris:
var age_barParts = [];
age_barParts.push({
'test': 'HIV',
'u16': 3,
'16-20': 5,
'21-25': 1,
'26-30': 2,
'31-49': 8,
'50+': 2
});
age_barParts.push({
'test': 'HIV Instant',
'u16': 1,
'16-20': 4,
'21-25': 0.05,
'26-30': 0.05,
'31-49': 7,
'50+': 3
});
var age_bar = Morris.Bar({
element: 'age_bar',
data: age_barParts,
xkey: ['test'],
ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
hideHover: 'auto',
resize: 'true',
gridTextSize: 16,
gridTextColor: '#5cb85c',
xLabelAngle: '70',
resize: true,
padding: 40
});
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<div id="age_bar" style="height: 450px;"></div>
As alternative you can adopt Highcharts which has a specific plotOption.
Below an example with Highcharts:
$(function () {
$('#age_bar').highcharts({
chart: {
type: 'column'
},
title: {
text: 'HIV stats'
},
xAxis: {
categories: ['HIV', 'HIV Instant']
},
yAxis: {
title: {
text: '#'
}
},
plotOptions: {
column: {
minPointLength: 3
}
},
colors: ["#0b62a4","#7a92a3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],
series: [{
name: 'u16',
data: [1, 0]
}, {
name: '16-20',
data: [5, 4]
}, {
name: '21-25',
data: [1, 0]
}, {
name: '26-30',
data: [2, 0]
}, {
name: '31-49',
data: [8, 7]
}, {
name: '50+',
data: [2, 3]
}],
});
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<div id="age_bar" style="height: 450px;"></div>
Update:
Here is a jsfiddle (for Morris) which modifies the hover legend replacing 0.05 with 0. You can improve this approach editing the hoverCallback function:
https://jsfiddle.net/beaver71/zm8wt4pj/
If you compile from coffee script files, just add after lastTop += size in morris.bar.coffee
if size == 0 then size = 1
Otherwise, if you just want to modify the javascript file, just add after lastTop += size; in morris.js
if (size === 0) { size = 1; }

Using different symbols for plotting data not working

I am attempting to use a different symbol for one of my data series on my flot graph as it is at a much larger scale then the rest of the data. I am using this example as reference: http://www.flotcharts.org/flot/examples/symbols/index.html
Here is what I have so far:
My includes:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.flot.js"></script>
<script type="text/javascript" src="jquery.flot.symbol.js"></script>
I then configure my flot options like so:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1},
series: { points : { show: true } }
};
I then actually plot the data:
$.plot('#placeholder', [{
data: my_data,
lines: { show : true},
points: { symbol: "square"},
color: '#CB4B4B',
label: 'My Data'
}], options);
}
However, flot is still graphing the points as the default circle. I get no error messages in firebug and I have even tried adding a logging message in the jquery.flot.symbol.js library itself to see if the "square" handler is even being called like so:
var handlers = {
square: function (ctx, x, y, radius, shadow) {
console.log("Square handler was called");
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.rect(x - size, y - size, size + size, size + size);
},
I am getting no console messages so I am assuming the handler is not getting called correctly. Am I missing something here?
EDIT:
Example of data I am trying to plot:
var d1 = [
[1364342400000, 208],
[1364346000000, 107],
[1364353200000, 42],
[1364371200000, 1680],
[1364360400000, 52],
[1364349600000, 67],
[1364385600000, 1118],
[1364367600000, 163],
[1364382000000, 1359],
[1364378400000, 1468],
[1364389200000, 1023],
[1364356800000, 63],
[1364374800000, 1601],
[1364392800000, 556],
[1364364000000, 84],
],
d2 = [
[1364342400000, 86],
[1364346000000, 42],
[1364353200000, 13],
[1364371200000, 458],
[1364360400000, 10],
[1364349600000, 22],
[1364385600000, 453],
[1364367600000, 45],
[1364382000000, 369],
[1364378400000, 379],
[1364389200000, 358],
[1364356800000, 17],
[1364374800000, 471],
[1364392800000, 147],
[1364364000000, 16],
],
d3 = [
[1364342400000, 7],
[1364346000000, 5],
[1364382000000, 11709],
[1364371200000, 58336],
[1364360400000, 1],
[1364349600000, 1],
[1364367600000, 2],
[1364389200000, 1191],
[1364378400000, 9085],
[1364385600000, 4688],
[1364374800000, 9386],
[1364392800000, 1140],
[1364364000000, 1],
];
I have also edited my options parameter and how the plot function is called:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1}
};
$.plot("#placeholder", [{
data: d1,
lines: { show : true },
points: { show: true},
color: '#EDC240',
label: "d1"
}, {
data: d2,
lines: { show : true },
points: { show : true},
color: '#AFD8F8',
label: "d2"
}, {
data: d3,
yaxis: 2,
lines: { show : true},
points: { show: true, symbol: "square"},
color: '#CB4B4B',
label: "d3"
}], options);
I am also sure that the symbol library is being included because I have added some logging itself to the library and that is showing up fine.
I see no issue with what you've done. I made a quick working example here: http://jsfiddle.net/ryleyb/shLtU/1/
I would guess that you haven't included the symbol library (even though you say you have).
Or show your data, might somehow be an issue there (doubtful?).
This is the full flot code I ran to make a working example (plus including flot and the symbol library):
$.plot('#placeholder', [{
data: [
[1, 1],
[2, 3],
[4, 4],
[5, 9]
],
lines: {
show: true
},
points: {
show: true,
symbol: "square"
},
color: '#CB4B4B',
label: 'My Data'
}]);

Categories

Resources