I receive some datas with ajax, and I would like to display it as google line charts. I don't know how many chart I have to display, so I have made it dynamic using a javascript forEach to call my function drawchart();
Here I receive the datas :
$j.ajax({
type: "GET",
url: "../"+folder_destination+"slimrest/getValues",
data: "",
success: function(msg){
msg.forEach(function(entry) {
drawchart(entry['id'], entry['data']);
});
}
});
Here is my function which is supposed to add a div with a unique ID then draw the chart inside :
function drawchart(id_rec){
$j("#charts_cartes").append("<div id=\"gchart_"+id_rec+"\"></div>");
var data = new google.visualization.DataTable();
data.addColumn('number', 'max');
data.addColumn('number', 'min');
data.addColumn('number', 'Mesures');
//Will be dynamic as soon as I'll be able to print more than one chart
data.addRows([
[1, 37.8, 80.8],
[2, 30.9, 69.5]
]);
var options = {
width: 500,
height: 200
};
var chart = new google.charts.Line(document.getElementById('gchart_'+id_rec));
chart.draw(data, options);
}
I see my divs in the html code, but the second chart is never displayed.
It seems that the <svg></svg> balise is empty for one of the charts :
<div id="charts_cartes">
<div id="gchart_39">
<div style="position: relative; width: 500px; height: 200px;">
<div
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;">
<svg width="500" height="200">
<defs><!-- [chart code well displayed but too long to write here] --></defs>
</svg>
</div>
</div>
</div>
<div id="gchart_40">
<div style="position: relative; width: 500px; height: 200px;">
<div
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;">
<svg width="500" height="200">
<defs></defs></svg>
</div>
</div>
</div>
</div>
Problem fixed adding a setTimeout to the draw function of the googlechart :
setTimeout(function(){ chart.draw(data, options); }, 1000);
There must be some conflicts if drawing to much charts almost simultaneously ...
The solution above works, but setTimeout with just 1 millisecond works, so that if you're dynamically generating the charts with some display logic, it won't be loading for 1000 milliseconds.
So this also worked for me in an AngularJS app.
setTimeout(function(){ chart.draw(data, options); }, 1);
Related
I was trying to create 3 charts using google charts in a single line.but it not showing the labels for the values and we can see there is lot of space was vacant in between the charts.is there any way to remove that space and show the labels properly in the graph?
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 5],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
pieSliceText: 'value',
pieHole: '0.5',
legend: {
position: 'labeled',
labeledValueText: 'both',
textStyle: {
color: 'blue',
fontSize: 14
}
},
};
var chart1 = new google.visualization.PieChart(document.getElementById('chart1'));
var chart2 = new google.visualization.PieChart(document.getElementById('chart2'));
var chart3 = new google.visualization.PieChart(document.getElementById('chart3'));
options.title = 'industries For USA';
chart1.draw(data, options);
options.title = 'Categories For USA';
chart2.draw(data, options);
options.title = 'Categories For Construction';
chart3.draw(data, options);
}
.chart-wrapper {
float: left;
width: 33%;
}
.top-five-charts {
width: 100%;
display: block;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="top-five-charts">
<div class="chart-wrapper">
<div id="chart1" class="insight-pie"></div>
</div>
<div class="chart-wrapper">
<div id="chart2" class="insight-pie"></div>
</div>
<div class="chart-wrapper">
<div id="chart3" class="insight-pie"></div>
</div>
</div>
Here is the output in normal screen
Just add this line on your JavaScript code before drawing the charts:
options.chartArea = {left: '10%', width: '100%', height: '65%'};
I've also changed the legend font size to 10.
It will look like this:
Here's the JSFiddle illustrating it: https://jsfiddle.net/6r3ms2tz/
You should have a look responsive design principles and please check out this link: https://developers.google.com/chart/interactive/docs/basic_customizing_chart
Simply change: 'legend':'right' according to the your choice.
After several tries, below worked:
Code:
let options = {
legend: {
position: "labeled",
},
chartArea: {
width: "100%"
}
};
HTML for my case is below because I am using https://github.com/FERNman/angular-google-charts
<google-chart
style="width: 100%; height: 100%;"
>
</google-chart>
HTML for your case:
<div id="chart1" class="insight-pie" style="width: 100%; height: 100%;" ></div>
Hope that helps.
I am using angular js with jssor slider as follow.
As far as I am concern, there is no $destroy method for jssor slider yet. But I need the user to click on the refresh button and reinit the jssor slider.
As you can see, currently it won't work if i reinit the jssor slider by clicking the refresh function.
I do not want to call .remove() function and bind back the html as it seems to be less angular way. Is there any other method?
I can't create own $destroy method as the jssor slider library source code is uglify.
angular.module('app', [])
.controller('FrameController', ['$scope', '$injector', function($scope, $injector) {
initSlider();
$scope.refresh = initSlider;
function initSlider() {
var image = [];
var count = Math.floor(Math.random() * 6) + 1;
for (var i = 0; i < count; i++) {
image.push('https://unsplash.it/600/' + i * 100 + '?random');
}
$scope.image = image;
console.log($scope.image);
function jssor_slider1_init(containerId) {
var options = {
$AutoPlay: 1
};
var jssor_slider1 = new $JssorSlider$(containerId, options);
};
setTimeout(function() {
jssor_slider1_init('slider1_container');
});
}
}]);
setTimeout(function() {
angular.bootstrap(document.getElementById('body'), ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jssor-slider/25.2.0/jssor.slider.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<div id="body">
<div ng-controller="FrameController">
<button ng-click="refresh()">
Click to refresh
</button>
<div id="slider1_container" style="position: relative; top: 0px; left: 0px; width: 600px; height: 300px;">
<!-- Slides Container -->
<div u="slides" style="cursor: move; position: absolute; overflow: hidden; left: 0px; top: 0px; width: 600px; height: 300px;">
<div ng-repeat="item in image track by $index">
<img ng-src="{{item}}" /></div>
</div>
</div>
</div>
Hello I would like to convert several rectangles graphs where I am taking datas from title and convert it with chartist.js to donut graph. I was thinking to do this with for loop through all ct-chart(its a day) and init the chartist on every day and push the data there but the problem is that when I initialize the graph the data are taken one by one so basically in the first donut graph is only first data so Support3L (E) without AnnualLeave (E) which is in the second day. I am trying to have Support3L(E) and AnnualLeave (E) in first ct-chart graph and Training (E) and Work(E) in second.
I think the problem is in
for (i = 0; i < $graphContainer.length; i++) {
graphValue[i] = $graphsE.eq(i).width(),
graphClass[i] = $graphsE.eq(i).attr('class');
...
but I dont know how to take all graphsE data and add it to one graphValue or is it something else ?
DEMO: https://jsfiddle.net/767ndb9s/11/
html:
<div title="13. 6." class="WorkDayInnerDivEven ct-chart">
<div title="Support3L (M)
8:00 - 16:00 (8h)" class="Event_Support3L work-day-graph" style="left: 40%; width: 30%; display: none;">
</div>
<div title="AnnualLeave (M)
9:00 - 17:00 (8h)" class="Event_AnnualLeave work-day-graph" style="left: 43.75%; width: 30%; display: none;">
</div>
<div title="Support3L (E)
8:00 - 16:00 (8h)" class="Event_Support3L work-day-graph" style="left: 40%; width: 30%; top: 85%; display: none;">
</div>
<div title="AnnualLeave (E)
9:00 - 17:00 (8h)" class="Event_AnnualLeave work-day-graph" style="left: 43.75%; width: 30%; top: 35%; display: none;">
</div>
</div>
<div title="14.6" class="WorkDayInnerDivEven ct-chart">
<div title="Training (M)
3:00 - 8:00 (5h)" class="Event_Training work-day-graph" style="left: 21.25%; width: 18.75%; display: none;">
</div>
<div title="Overtime (M)
8:00 - 16:00 (8h)" class="Event_Overtime work-day-graph" style="left: 40%; width: 30%; display: none;">
</div>
<div title="Work (M)
17:00 - 23:00 (6h)" class="Event_Work work-day-graph" style="left: 73.75%; width: 22.5%; display: none;">
</div>
<div title="Training (E)
3:00 - 8:00 (5h)" class="Event_Training work-day-graph" style="left: 21.25%; width: 18.75%; top: 35%; display: none;">
</div>
<div title="Overtime (E)
8:00 - 16:00 (8h)" class="Event_Overtime work-day-graph" style="left: 40%; width: 30%; top: 35%; display: none;">
</div>
<div title="Work (E)
17:00 - 23:00 (6h)" class="Event_Work work-day-graph" style="left: 73.75%; width: 22.5%; top: 35%; display: none;">
</div>
</div>
JS:
var circlesLayout = function() {
var $graphContainer = $('.ct-chart'),
//only the graph with (E) in title is used for donut graph not overtime
$graphsE = $graphContainer.find('.work-day-graph[title~="(E)"]').not('.work-day-graph[title~="Overtime"]'),
graphValue = [$graphsE],
graphClass = [];
//hide desktop rectangle-graph
$('.ct-chart div.work-day-graph').hide();
//add class circles (its for css)
$('html').addClass('circles');
//init chartist
for (i = 0; i < $graphContainer.length; i++) {
graphValue[i] = $graphsE.eq(i).width(),
graphClass[i] = $graphsE.eq(i).attr('class');
new Chartist.Pie($graphContainer[i], {
series: [{
value: graphValue[i],
className: graphClass[i]
}]
}, {
donut: true,
donutWidth: 10,
donutSolid: true,
startAngle: 270,
showLabel: false
});
}
}
circlesLayout();
As I understand you have 4 events where title contains (E), two of them have to be graphed on first chart and the other two on the second graph.
You need to modify the for statement where you think the problem is, the goal is populate an array of data before you initialize the chartist plugin, I did some modifications:
// Array of events
var events = []
events[0] = ['Support3L', 'AnnualLeave']
events[1] = ['Training', 'Work']
//init chartist
for (i = 0; i < $graphContainer.length; i++) {
var series = [];
for(j=0; j< $graphsE.length; j++){
// fill series with the data you want to graph
// in this case filter Support3L(E) and AnnualLeave (E) for the first
// Training (E) and Work(E) for the second
if(events[i].some(evt=>$graphsE.eq(j).attr('class').includes(evt)))
series[j] = {
value: $graphsE.eq(j).width(),
className: $graphsE.eq(j).attr('class'),
label: j
};
}
new Chartist.Pie($graphContainer[i], {
// Set data to graph
series: series
}, {
donut: true,
donutWidth: 10,
donutSolid: true,
startAngle: 270,
showLabel: false
});
}
Those changes already are on your fiddle
I have placed this following code inside a loop and the chart is not displaying as desired.I have used google gauge chart to display the age of University. I have also attached the screenshot for more reference.
<h5>Age of <span class="text-primary"><?php echo $uni_name; ?></span></h5>
<?php
$est=date('Y')-$uni_establish;
?>
<p style="font-family: Serif; font-size: 170px; color:green; align:center"><b><?php echo $est;?></b></p>
<script type="text/javascript">
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Age', <?php echo $est;?>],
]);
var options = {
width: 600, height: 320,
yelloFrom: 0, yellowTo: 100,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
<div id="chart_div" style="width: 600px; height: 320px;"></div>
</section>
If this code is inside the loop means div with id chart_div will be appear multiple times, use an increment variable.
I am having problems with the fact that my javascript background is overtaking everything and not showing any html elements. I would like it so that my button and digits show up in front of the background.
Example :
Code
window.onload = function() {
var paper = new Raphael(200, 200, 600, 600);
var backGround = paper.rect(0, 0, 600, 600);
backGround.attr({
fill: "#ffb366"
});
}
<div class= "bot">
<input type="button" value="Start" onclick="start();"/>
<span id="timers">0</span>
</div>
Try to add
.bot {
position: relative;
z-index: 1;
top: 200px;
left: 200px;
}
Instead of putting your timer button inside bot class you can create a separate div and style it with the required margins. The html code looks like below:
<div class= "bot">
</div>
<div style="top:200px;left:200px;z-index:10;position:absolute;">
<input type="button" value="Start" onclick="start();"
style="z-index:10"/>
<span id="timers">0</span>
</div>
Here is the required CSS:-
.bot {
position: absolute;
top: 200px;
left: 200px;
z-index:1;
}
And try to write the javascript as below:-
window.onload = function() {
var element=document.getElementsByClassName('bot')[0];
var paper = new Raphael(element, 600, 600);
var backGround = paper.rect(0, 0, 600, 600);
backGround.attr({
fill: "#ffb366"
});
}
It looks like, z-index property does not work if the button is inside raphael class. Good luck.