How to refresh jqplot bar chart without redrawing the chart - jquery-plugins

I have a jqplot bar chart and I want the chart data to be changed when the user changes the value on a drop-down list. That works, but the problem is the bar chart redraws, one over another, each time the user changes the values.
How can I update or reload the bars without drawing the whole thing again? Is there any property value to be set?
Chart data changes according to an ajax call:
$.ajax({
url: '/Home/ChartData',
type: 'GET',
data: { Id: Id },
dataType: 'json',
success: function (data) {
$.jqplot('chartDiv', [a, b], CreateBarChartOptions(xAxis));
}});
function CreateBarChartOptions(xAxis) {
var optionsObj = {
title: 'Stat',
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: xAxis
},
yaxis: { min: 0 }
},
series: [{ label: 'A' }, { label: 'B'}],
seriesDefaults: {
shadow: true,
renderer: $.jqplot.BarRenderer,
rendererOptions: {
barPadding: 8,
barMargin: 10
}
},
};
return optionsObj;
}
A reply would be highly appreciated. Thanks.

What you want to do is call jqPlot's .replot() method when you draw the new chart. Change your ajax call to look like this:
$.ajax({
url: '/Home/ChartData',
type: 'GET',
data: { Id: Id },
dataType: 'json',
success: function (data) {
$.jqplot('chartDiv', [a, b], CreateBarChartOptions(xAxis)).replot();
}});

Try having your chart object as a global variable in your script as:
var plot1 = $.jqplot('chartDiv', [a, b], CreateBarChartOptions(xAxis));
Then on success reset the data, axesScale and replot as:
var newData = [['a',1],['b',2],['c',3]];
plot1.series[0].data = newData;
plot1.resetAxesScale();
plot1.replot();
Ref: https://groups.google.com/group/jqplot-users/browse_thread/thread/59df82899617242b?pli=1

Each time before redrawing the graph, just destroy the existing1.
$.ajax({
url: '/Home/ChartData',
type: 'GET',
data: { Id: Id },
dataType: 'json',
success: function (data) {
if(plot)
{
plot.destroy();
}
var plot=$.jqplot('chartDiv', [a, b], CreateBarChartOptions(xAxis));
}});

Took me a while to find an answer for the script generated data, so I'm going to post this right here. I used a combination of the above code.
I created a global var, named plot3 within my script file. Then created the below function. When this is called with a redraw boolean, it determines if I need to destroy and redraw or draw for the first time.
What first bit of code does is gets data from my jqgrid, (which is being updated in a different function), and updates the arrays. The second bit, determines my interval ticks, on the x-axis dependent upon my length of data.
function DrawGraph(bRedraw){
var testTimes = [];
testTimes = $('#polarizationTable').jqGrid('getCol', 'TestTime', testTimes, false);
var RdgA = $('#polarizationTable').jqGrid('getCol', 'RdgA', RdgA, false);
var RdgB = $('#polarizationTable').jqGrid('getCol', 'RdgB', RdgB, false);
var readingLineA = [];
for (var i=0; i<testTimes.length; i++){
readingLineA.push([testTimes[i], RdgA[i]]);
}
var readingLineB = [];
for (var i=0; i<testTimes.length; i++){
readingLineB.push([testTimes[i], RdgB[i]]);
}
var maxX = $("#testLength").val();
var lengthX = testTimes.length;
var tickIntervalX = Math.round(maxX/10);
if(bRedraw == true)
{
plot3.destroy();
bRedraw = false;
}
if(bRedraw == false)
{
plot3 = $.jqplot('chart3', [readingLineA, readingLineB],
{
title:'Graph',
series:[{label:'Reading - A'}, {label:'Reading - B'} ],
legend:{show:true, location:'se'},
// You can specify options for all axes on the plot at once with
// the axesDefaults object. Here, we're using a canvas renderer
// to draw the axis label which allows rotated text.
axes:{
xaxis:{
label:'Minutes',
syncTicks: true,
min: 0,
numberTicks: 10,
tickInterval: tickIntervalX,
max: maxX*1.1,
labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
labelOptions: {
fontSize: '12pt'
},
},
yaxis:{
label:'Data',
min: 0,
numberTicks: 10,
labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
labelOptions: {
fontSize: '12pt'
}
},
}
});
}
}

Here is a full example of how to dynamically update the plot with new data without reloading the page:
<div id="chart1" style="height: 300px; width: 500px; position: relative;"></div>
<button>New data point</button>
<script type="text/javascript">
var storedData = [3, 7];
var plot1;
renderGraph();
$('button').click( function() {
doUpdate();
});
function renderGraph() {
if (plot1) {
plot1.destroy();
}
plot1 = $.jqplot('chart1', [storedData]);
}
function doUpdate() {
var newVal = Math.random();
storedData.push(newVal);
renderGraph();
}
</script>
It's a simplified version of this guy's post: JQPlot auto refresh chart with dynamic ajax data

$('#chart).html('');
chart is the DIV where chart is created.
this does the trick, nothing fancy by effective.

Maybe this will help. I on the other hand is having problem with getting replot to work at all, but i'am using a dataRenderer.
$.ajax({
url: '/Home/ChartData',
type: 'GET',
data: { Id: Id },
dataType: 'json',
success: function (data) {
$('chartDiv').empty();
$.jqplot('chartDiv', [a, b], CreateBarChartOptions(xAxis));
}});

hope this helps
jQuery(document).ready(function(){
jQuery.ajax({
url: '/review_graphs/show',
type: 'GET',
success: function (data) {
var plot1 = jQuery.jqplot('chartDiv', [data,data],
{
title: 'Bianual Reviews percentage',
series:[
{
renderer:jQuery.jqplot.BarRenderer,
label:'Average',
stackSeries: true,
dragable: {color: '#ff3366',constrainTo: 'x'},
trendline:{show: false}
},
{
label:'Trend Line',trendline:{show: false}}
],
legend: {
show: true,
placement: 'outsideGrid'
},
axesDefaults: {
tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer ,
tickOptions: {
angle: -30,
fontSize: '10pt'
}
},
axes: {
xaxis: {
renderer: jQuery.jqplot.CategoryAxisRenderer
}
}
});
}});
});

The best method I got is, the div in which you're drawing, clear that before you draw your new graph.
$('#graph_area).children().remove();

Related

How can I generate a real-time highchart from my database data?

I have looked at the following links Binding json result in highcharts for asp.net mvc 4 , highcharts with mvc C# and sql, HighChart Demo and many others. However, I couldn't find a working demo showing how to implement a highchart using data from a database.
Objective:
I want to generate a real time highchart line graph getting data from my database. What I want is very similar to the third link which provides a real-time highchart with randomly generated values. It is also similar by X-axis and Y-axis, for I want my x-axis to be "Time" (I have a DateTime column in my database) and y-axis to be an integer (I have a variable for that as well in my database).
Please I need help in sending the model data to my razor view.
Note that I am already using SignalR to display a realtime table. I also want to know if it can be used to automatically update the highchart as well.
Below is the code snippet of my script in the view. I have used the code provided in link 3 for generating the highchart. Please tell me where should I apply the changes on my code.
#section Scripts{
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/SignalR/Hubs"></script>
<script type="text/javascript">
$(document).ready(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.dataHub;
//debugger;
// Create a function that the hub can call to broadcast messages.
notifications.client.updateMessages = function () {
getAllMessages()
};
// Start the connection.
$.connection.hub.start().done(function () {
alert("connection started")
getAllMessages();
}).fail(function (e) {
alert(e);
});
//Highchart
Highcharts.setOptions({
global: {
useUTC: false
}
});
//Fill chart
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.random();
series.addPoint([x, y], true, true);
}, 1000);//300000
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
}())
}]
});
});
function getAllMessages() {
var tbl = $('#messagesTable');
var data = #Html.Raw(JsonConvert.SerializeObject(this.Model))
$.ajax({
url: '/home/GetMessages',
data: {
id: data.id,
},
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
$("#g_table").dataTable();
}).error(function (e) {
alert(e);
});
}
</script>
}
UPDATED CODE
//Highchart
Highcharts.setOptions({
global: {
useUTC: false }
});
//Fill chart
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: $.connection.hub.start().done(function () {
alert("Chart connection started")
var point = getAllMessagesforChart();
var series = this.series[0];
setInterval(function (point) {
// add the point
series.addPoint([point.date_time, point.my_value], true, true)
}, 1000);
}).fail(function (e) {
alert(e);
})
}
}
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'Value',
margin: 80
}
},
series: [{
name: 'Random data',
data: []
}]
});
function getAllMessagesforChart() {
var data = #Html.Raw(JsonConvert.SerializeObject(this.Model))
$.ajax({
url: '/home/GetMessagesforChat',
data: {
id: data.id,
},
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (data) {
data = JSON.parse(data);
//data_graph = [].concat(data);
//$("#debug").html(data_graph);
}).error(function (e) {
alert(e);
});
return data;
//return data_graph;
}
There is an example that might help you:
http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/line-ajax/
it uses an ajax callback function.
Well, you can also have a look at my sample where I add dynamically series by clicking add button.
http://plnkr.co/edit/Sh71yN?p=preview
You only need to add data in the right structure.
Have a look at the function
$("#btnAdd").click(function()
of my code script.js
I hope it helps.
regards,
Luis

HighChart Pie Dynamic JSON in Codeigniter

Any help for this? The problem is I cannot get the data in pie. Any ideas? I tried to echo it outside the pie graph view, and the data appears in JSON as [{"Terminal":"13"}]. The Hightchart needs the data as ["Sample", 2]? Any suggestion sir on how to convert it like that? Thanks.
Heres my code:
VIEW
$(document).ready(function () {
$(function () {
var chart;
// Build the chart
$('.widget-lower-left#widget').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: 'Availability'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage}%</b>',
percentageDecimals: 1
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
type: 'pie',
name: 'Availability',
data: []
}]
});
});
function requestData() {
$.ajax({
url: 'home',
datatype: "json",
success: function(data) {
alert(data);
console.log(data);
chart.series[0].setData(data);
},
cache: false
});
};
});
then in the MODEL
$results = $this->db->query("SELECT COUNT(get_jeeps_availability) as Terminal FROM get_jeeps WHERE get_jeeps_availability = 'Terminal'");
return $results->result_array();
in the CONTROLLER
public function index()
{
$data['pie'] = json_encode($this->get_model->dashboard_jeep_widget());
$this->load->view('home',$data);
}
In requestData() function, before setting data, preprocess 'data' that way:
var newData = [];
for( var i = 0, len = data.length; i < len; i++ ) {
var item = data[i];
for(var j in item){
newData.push([j,item[j]]);
}
}
chart.series[0].setData(newData);

Dynamic Flot chart using Ajax

I'm new to javascript and flot and hope someone can help me with this problem I'm having.
What I'm trying to achieve it have a dynamic flot graph on a page.
The data for the series that is to be plotted is in a file that will get updated every few seconds. I want the flot graph to read the data file every few seconds and be updated with the new data.
Here's the code I've got which isn't working. The graph displays ok on page load, but just doesn't get updated every 5 seconds.
Any help is much appreciated.
$(function () {
var dataFolder = "http://localhost/graphdata/";
/***********************************************************************
* Function to get series data from a file
***********************************************************************/
function getSeriesData(file) {
var url= dataFolder + file;
var data = null;
$.ajax({
async: false,
url: url,
method: 'GET',
dataType: 'json',
success: function(datasets){
data = datasets;
},
error: function(error,text,http){
alert(error + " " + text + " " + http);
}
});
return data;
}
var plot = $.plot($("#placeholder"),
[
{label: "A", data: getSeriesData("dataA.txt")},
{label: "B", data: getSeriesData("dataB.txt")},
{label: "C", data: getSeriesData("dataC.txt")}
],
{
series: {
lines: {
color: "red",
show: true
},
points: {
show: true
},
shadowSize: 0,
hoverable: true
},
colors: ["red", "blue", "green"],
yaxis: {
min: 0, ticks:5
},
xaxis: {
mode: 'time',
timeformat: '%H:%m',
show: false
},
legend:{
show: true
},
grid:{
color: "green",
show: true,
backgroundColor: "white",
hoverable: true
}
}
);
var updateInterval = 1000 * 5;
function update() {
plot.setData([
{label: "A", data: getSeriesData("dataA.txt")},
{label: "B", data: getSeriesData("dataB.txt")},
{label: "C", data: getSeriesData("dataC.txt")}
]);
plot.setupGrid();
plot.draw();
setTimeout(update, updateInterval);
}
update();});
I figured it out. The ajax call for the file was being cached in the browser so any further calls for the same file would have been returned from cache, making it look like no updates to the graph were happening. Switch caching of in the function and it works fine now.
function getSeriesData(file) {
var url= dataFolder + file;
var data = null;
$.ajax({
async: false,
cache: false,
url: url,
method: 'GET',
dataType: 'json',
success: function(datasets){
data = datasets;
},
error: function(error,text,http){
alert(error + " " + text + " " + http);
}
});
return data;
}
It seems to update correctly for me using numbers. Can you provide a few data examples?
I changed the x axis and data pull but the updating worked fine.
function getSeriesData() {
var randomnumber=Math.floor(Math.random()*11)
var randomnumber2=Math.floor(Math.random()*11)
var data = [
[randomnumber, randomnumber2],
[randomnumber +1, randomnumber2 +2],
[randomnumber +3, randomnumber2 +4],
[randomnumber +5, randomnumber2 +6],
[randomnumber +7, randomnumber2 +8],
];
return data;
}
fiddle - http://jsfiddle.net/EX6dv/1/
It seems you need to put following out side the update function too.
setTimeout(update, updateInterval);

Load data into Highcharts with Ajax

I am trying to update high charts on page load and on select menu change with JQUERY AJAX call. There is data being returned in [[10,1228800000],[10,1228800000]] format.The chart is blank and does not graph any of the data.
Tried several solutions posted on here but none worked.
var chart;
$(document).ready(function() {
var options = {
chart: {
renderTo: 'stats',
defaultSeriesType: 'spline'
},
title: {text:''},
xAxis: {
type: 'datetime'
},
yAxis: {},
series: []
};
var month = 'July';
$.ajax({
type: "POST",
data: "month="+month,
url: "update_visits_chart",
success: function (data) {
options.series.push(data);
chart = new Highcharts.Chart(options);
}
});
Any errors? thanks in advance.
EDIT:
MOST RECENT CODE STILL NOT WORKING:
var options = {
chart: {
renderTo: 'stats',
type: 'spline'
},
title: {
text: ''
},
xAxis: {
type:'datetime',
tickInterval: 30 * 24 * 3600 * 1000,
dateTimeLabelFormats: {
day: '%b %e'
},
labels: {
rotation: -45,
align: 'right'
}
},
yAxis: {
title: {
text: 'Number of visits'
},
min: 0
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat('%b %e', this.x) +'<br />'+this.y+' visit(s)';
}
},
legend: {
enabled: true
},
credits: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Number of Visits',
data: []
}]
};
var month = 'July';
$.ajax({
type: "POST",
url: "update_visits_chart",
data: "month="+month,
success: function(data){
options.series[0].data = data;
chart = new Highcharts.Chart(options);
}
});
You have to use the setData methode of the series object as descriped in documentation. In your case it is options.series[0].setData(Data)
And I think you have to turn your Ajax result from string to a real object/array by using JSON.parse(data).
EDIT:
#Ricardo Lohmann: in the ajax-call he did not specify the dataType he expects in the response, so jQuery will guess the dataType. But it will not recognize a string starting with [ as JSON and I doubt his response will be served with correct mime type application/json. So specifying the correct mime type should also solve the problem. But I do not have an example of the complete ajax respons of the questioner. So I'm just guessing, too.
I'd recommend the following ajax call:
$.ajax({
type: "POST",
url: "update_visits_chart",
data: {month: month},
dataType: 'json',
success: function(data){
options.series[0].setData(data);
}
});
#Jugal Thakkar
$.getJSON is just a shortcut for the ajax-call above, but it is less flexible because you have less options.
You have to set directly data to series because data is already a multidimensional array.
The following code will fix it.
Change options.series.push(data); to options.series = data;

Jqplot pie chart rendering only lines

am loading jqplot corresponding files dynamically and passed data to the and chart div but at sometimes am getting the graph and some other time am not getting the graph my code as follows i maid an ajax call to get the values and passed to the graph in object st and the output am getting is shown here http://i43.tinypic.com/wcfns0.png please help me function
jsFunction3(xyz) {
jQuery.getCSS = function( url, media )
{
jQuery( document.createElement('link') ).attr({ href: url, media: media || 'screen', type: 'text/css', rel: 'stylesheet' }).appendTo('head'); };
$.getCSS('/redkanproject/plugins/jqplot-0.1/css/jqplot/jquery.jqplot.css','print');
$.getScript('/redkanproject/plugins/jqplot-0.1/js/jqplot/jquery.jqplot.min.js',
function() { }); $.getScript('/redkanproject/plugins/jqplot-0.1/js/jqplot/excanvas.min.js', function() { });
$.getScript('/redkanproject/plugins/jqplot-0.1/js/jqplot/plugin/jqplot.pieRenderer.min.js', function() { });
var JSONObject = new Object;
JSONObject.id =xyz;
JSONstring = JSON.stringify(JSONObject);
var url = "${createLink(controller:'page', action:'example4')}"; new Ajax.Request(url, { method:'post', contentType:'application/json', postBody:JSONstring, asynchronous:true, onSuccess: function (res) {
st=(res.responseJSON)
x="chart" // this is my div to display chart
var plot1 = $.jqplot (x, [st], { title: 'Bianual Reviews percentage', grid: {
background:'#834100', shadow: true,borderWidth: 0, borderColor: 'white',shadowDepth: 0}, seriesDefaults: {
// Make this a pie chart.
renderer: $.jqplot.PieRenderer, rendererOptions: {
// Put datalabels on the pie slices.
// By default, labels show the percentage of the slice.
sliceMargin:6,
showDataLabels: true
}
},
legend: { show:true, location: 'e' } } );
$(x).bind('jqplotDataClick', function(ev,seriesIndex, pointIndex, data)
{ alert(" data: "+data); }
);
}
})//ajax }
------------------------------------------------------------------------
I had a similar issue and it turned out that I had a global style on the table element which sets the width to 100%.
eg
table{
width:100%
}
I changed that to auto and everything displayed correctly
table{
width:auto;
}
Hope that helps :-)

Resources