how do you do ajax call in javascript - javascript

I am building a dashboard that will have buttons on top for monthly, weekly and real time data.
<div class="zoom_controls">
<a class="profile" id="monthly_data" href="#" data-chart="line" data-range="6m">Monthly</a>
<a class="profile" id="weekly_data"href="#" data-chart="line" data-range="3m">Weekly</a>
<a class="profile" id="real_time" href="#" data-chart="line" data-range="1m">Real Time</a>
</div>
<div class="main" id="chart" style="width:700px; height:300px;"></div>
This is the javascript that calls a php file to get the data and insert it into highcharts:
function cpu_current() {
//current_cpu_data.php retrieves the data from a flat file
$.getJSON('current_cpu_data.php', function(data) {
var chart = new Highcharts.StockChart({
chart: {
borderColor: '#98AFC7',
borderRadius: 20,
borderWidth: 1,
renderTo: 'chart',
type: 'line',
marginRight: 10,
zoomType: 'x'
},
exporting: {
enabled: true
},
legend: {
enabled: true,
backgroundColor: '#FCFFC5',
borderColor: 'black',
borderWidth: 2,
width: 500,
shadow: true
},
plotOptions: {
series: {
lineWidth:1
}
},
rangeSelector: {
enabled:false
},
scrollbar: {
enabled: false
},
navigator : {
enabled : false
},
xAxis: {
gridLineColor: '#EEEEEE',
gridLineWidth: 1
},
yAxis: { // Primary yAxis
labels: {
style: {
color: 'blue'
}
},
gridLineColor: '#EEEEEE',
gridLineWidth: 0,
tickInterval: 20,
min:0,
max:100,
plotLines : [{
value : 70,
color : '#FF3300',
dashStyle : 'line',
width : 1,
label : {
text : 'Threshold=70%',
align: 'right',
style: {
fontWeight: 'bold'
}
}
}],
title: {
text: '% CPU Utilization',
style: {
color: 'blue'
}
}
},
credits: {
enabled: false
},
title: {
text: 'CPU',
style: {
color: '#333000',
fontSize: '14px'
}
},
subtitle: {
text: '10 minute peaks in last 24 hours'
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y} </b><br>',
valueDecimals: 2
},
series:data
});
});
}
Here I can use jquery click event to switch between different tabs:
$("#monthly_data").click(function() {
hmms_cpu_current();
});
$("#weekly_data").click(function() {
hmms_cpu_weekly();
});
$("#real_time").click(function() {
cpu_current();
});
My question is this, when the user only interested in real_time and clicks and leaves it there, I need cpu_current() to update on its own via ajax calls. If a user clicks on monthly_data and leaves it there cpu_current() need to stop.
How would do this given the above code?

if you are using MVC Model you can use Ajax like this using onclick method of particular javascript function ,
<script type="text/javascript">
function hmms_cpu_current() {
$.ajax({
type: 'GET',
async: false,
url: 'yourcontroller/youraction',
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (data) {
var obj = $.parseJSON(data);
$.each(data, function (i, item) {
alert(item.text) // do your stuff with returned value
});
},
error: function () {
output.text('There was an error loading the data.');
}
});
}

I would add a Javascript Timer() or setTimeout() which re-sends the ajax call and updated the page.
You could also give the user the option of doing this and put it inside a Function.
If you give the Timer an ID, you can also stop and start it.

Modify all your functions to return a jqXHR like this:
function cpu_current() {
//$.getJSON return jqXHR, you could use it to abort ajax.
return $.getJSON('current_cpu_data.php', function(data) {
//All your code
}
The use abort in your event handlers:
var currentjqXHR;
$("#monthly_data").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = hmms_cpu_current();
});
$("#weekly_data").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = hmms_cpu_weekly();
});
$("#real_time").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = cpu_current();
});

Related

Multiple Charts not moving in sync at random times when adding value on interval

I am trying to create dynamic number of series from UI. Upon selection, backend updates one entry at the time. While the graphs are running fine at most times. At some random time the two series move out of sync as in http://jsfiddle.net/cRgUr/
and come back in sync after few seconds. I have referred following links for resolution but still see the issue.
Chart not moving fluently when adding value to two lines on interval and Updating spline chart two lines on top of eachother
Below is the code snippet :
function getInitialData(series){
var arrayOfValues=[];
$http({
mode:'cors',
method:'GET',
url: '/getData',
headers: { 'Content-Type':'application/json' },
cache: false,
}).success(function(data) {
arrayOfValues.push(/*populated by backend*/); // E.g values for y for number of series selected. If 2 series are to be drawn, at a time this array will contain arrayOfValue[0]= y value for series 1, arrayOfValue[1]=y value for series 2
}
drawgraph(series,arrayOfValues,newWidgetMetrics/*widget selected from UI*/);
} ).error(function(data) {
});
function drawgraph(series,arrayOfValues,newWidgetMetrics1){
var time = (new Date()).getTime();
for(let p=0;p<arrayOfValues.length;p++){
if(p<arrayOfValues.length-1){
series[p].addPoint([time,arrayOfValues[p]] ,false
, (series[0].data.length >= 20));// set false for all series but the last, with an animation where we want the line to start plotting after 20 seconds
}
else{
series[p].addPoint([time,arrayOfValues[p]] , true
, (series[0].data.length >= 20));// set true for only the last series, with an animation where we want the line to start plotting after 20 seconds
}
chart.redraw();
}
arrayOfValues=[];
}
dataSeries=function(){
for(var i=0;i<length;i++){
var obj={};
obj.type="line";
obj.data=getData();
obj.boostThreshold=60;
obj.name=newWidgetLegends[i];
tArray.push(obj);
}
return tArray;
}
func_plot();
function func_plot(){
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
chart=Highcharts.chart(divId, {
chart: {
height:'38%',
zoomType: 'x',
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
maxSamples = 60,
counter = 0;
// set up the updating of the chart each second
var ser = this.series;
// setTimeout(function () {
setInterval(function (){
window['arr' + count]=[];
getInitialData(ser);
}, 1000);
}, 2000);
}
}
},
title: {
text: '',
style: {
display: 'none'
}
},
exporting: {
buttons: {
contextButton: {
y:screen.height*-0.02
}
}
},
plotOptions: {
line: {
marker: {
enabled: false
}
},
events: {
legendItemClick: function () {
return false;
}
}
},
xAxis: {
type: 'datetime',
ordinal:false,
labels: {
format: '{value:%M:%S}'
},
tickInterval: 10000,
title: {
text: newWidetXLabel,
marginBottom: 100
}
},
yAxis: {
title: {
text:newWidetYLabel,
min: 0,
max:10
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
title: {
text: '',
style: {
fontStyle: 'italic'
}
},
layout: 'horizontal',
align: 'right',
verticalAlign: 'top',
x: -30,
y: -17
},
boost: {
seriesThreshold:2,
useGPUTranslations: true
},
credits: {
enabled: false
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat('%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
series: dataSeries()
});
});
}
$(window).resize(function() {
height = chart.height,
width = chart.width,
chart.setSize(width, height, doAnimation = false);
});
}
}
}]);
This issue happens because both series are not being drawn at the same moment. Second argument of the addPoint function is a flag that indicates whether the chart should be redrawn immediately after the addition or not. In your code 2 redraws happen instead of one. The update of the second series breaks the animation of the first one (it has no time to finish).
The solution here is to redraw the chart only after the second call of addPoint():
series.addPoint([x, y], false, true);
series2.addPoint([x, y2], true, true);
Live demo: http://jsfiddle.net/kkulig/5y1dacxv/
API reference: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint

Have an issue with JavaScript, AJAX code displaying data

I need some tips from you out there to come over a good solution on my problem with JavaScript, AJAX and JSON data. I want to fill a generic set with barcharts (I am using HighCharts) on my web page. The data is in JSON format which from the start I only used date and value as pair data set. The solution works fine of I had only one bar chart it, but I have a lot of charts on my page and I need to show all of them (up to twelve).
Now I want to adjust for displaying more than one graph. In the code below the DataMacro array works fine with the chart. It also has a hard coded ID matching a . Now I have a series of in the page like id=barchart11, id=barchar21, and so on. In the dataset I have made a tag called PanelCodeUI that I am going to use looping through the dataset. The problem is how to do that. The each-loop will now fill in all date,value for all vessels.
And further it I need to restructure the function which is displaying the barchart. The best thing would be to call a function with a data array and panelCodeUI id just replacing the name of the barchart and set in the datamacro as is. But I don’t know how to do this. The data is mixed between all vessels and I need to collect all data before sending to a function. So is the problem with AJAX and JavaScript with is asynchron. I need to ensure that it behaves correctly and fast.
Maybe I need to change my dataset, or I need to do this in several step like finding all vessel IDs then do another AJAX call to get date,value pair from a vessel and then displaying. I hope there is a way to do this with this data set and hope somebody can help me on this
Here is a bit of the JSON data set:
[
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":844,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":8720,"VesselId":4,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"12","VesselSorting":2},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":948,"VesselId":5,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"11","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":0,"VesselId":6,"SectorId":3,"PanelCodeUI":"31","VesselCodeUI":"31","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465171200000,"Value":2067,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1}
]
And here is the JavaScript code so far:
$(function () {
var datamacro = [];
$.ajax({
type: "POST",
url: '../Services/HighChartService.asmx/GetOilProductionLast5DaysByActiveVessels',
data: '',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (seriedata) {
console.log(JSON.stringify(seriedata.d));
var productions = seriedata.d;
$.each(productions, function (index, productions) {
var yval = productions.Value;
var xval = productions.Date;
var x = [xval, yval];
datamacro.push(x);
//alert("productions Name: " + productions.Date + "\nID: " + productions.Value);
});
$(function () {
//var bchart = '#barchart' + vesselindex.toString();
// want this to be looped with generic names like #barchart11, #barchart21, #barchart31 and so on
$('#barchart11').highcharts({
chart: {
type: 'column'
},
title: {
text: 'LAST FIVE DAYS'
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}, series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: datamacro,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
},
error: function (r) {
alert(r.responseText);
},
failure: function (r) {
alert(r.responseText);
}
});
});
If i understand correctly, you would like to draw a chart for each different panelCodeUI ?
If that's the case, change your code after AJAX success with that :
var productions = seriedata.d;
var listPanelCodeUI = productions.map(function(p){return p.PanelCodeUI}).filter(function(item, pos, self) {
return self.indexOf(item) == pos;
});
//listPanelCodeUI : [21,11,31]
listPanelCodeUI.sort();
listPanelCodeUI.forEach(function(e){
datamacro = [];
//Create a div for each panelCodeUI
$("body").append("<div id='barchart" + e + "'></div>");
var divId = "#barchart"+e;
//Filter productions for specific panelCodeUI
var data = productions.filter(function(p){return p.panelCodeUI === e});
data.forEach(function(d){
var yval = d.Value;
var xval = d.Date;
var x = [xval, yval];
datamacro.push(x);
});
$(function () {
$(divId).highcharts({
...
})
})
}
That's what you need to parse your data:
charts = [];
$.each(productions.map(function(el) {
return el.PanelCodeUI;
}).filter(function(el, index, arr) {
return arr.indexOf(el) === index;
}), function(index,PanelCodeUI) {
var serie = productions.filter(function(el) {
return el.PanelCodeUI === PanelCodeUI;
});
$.each(serie, function(index, production) {
datamacro.push([production.Value, production.Date]);
});
drawChart('#barchart' + PanelCodeUI, 'LAST FIVE DAYS', datamacro);
});
Also i made this helper function to create the charts:
function drawChart(containerID, chartTitle, data) {
charts.push(new Highchart.Chart({
chart: {
type: 'column',
renderTo: containerID
},
title: {
text: chartTitle
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: data,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
}));
}

Highcharts heat map not displaying properly

I'm trying to create a heat map using Highcharts but it's not loading properly (just lines instead of the heat map itself).
I'm loading the data from a JSON file:
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
xAxis: {
categories: $scope.loadDays()
},
yAxis: {
categories: $scope.loadHours(),
title: null,
reversed: true
},
series: [{
name: null,
borderWidth: 1,
data: [],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
$scope.getHeatMapData = function(data) {
var response = [];
$scope.data = data;
if(data && $scope.data.timestamps && $scope.data.info) {
$scope.data.timestamps.forEach(function(element, index) {
if ($scope.data.info[index]) {
response.push([
moment(element).day(),
moment(element).hour(),
$scope.data.info[index]
]);
}
});
}
return response;
};
The data is being logged correctly to the console but, for some reason, the heat map isn't loading.
I've also created a Plunker where you can see its behavior.
Any ideas?
I was making a mistake when reloading the chart. I just had to add the type to the event:
chartConfig.chart = { type: 'heatmap', events: { load: callback } };
Plunker

Flot Chart : Adding Checkbox's to Toggle Chart Series

After setting up my first chart I'm looking to add check-boxs to toggle which series are selected.
Flot provides an example here : http://www.flotcharts.org/flot/examples/series-toggle/
Now when i tried to replicate this I'm getting error: 'datasets' is undefined could anyone explain why??
Also bonus points if anyone can tell my why the legend still display's inside the graph?
Chart Looks like :
View Code :
<div class="legend-container"></div>
<div class="graph-container">
<div id="placeholder" class="graph-placeholder"></div>
</div>
<p id="choices"></p>
Chart Code:
$(document).ready(function fetchData() {
function onDataReceived(series)
{
console.log('recieved data now parsing the data');
var currentdata = $.parseJSON(series);
//Testing
console.log(currentdata);
console.log("series sub-arrays");
console.log(currentdata[0]);
console.log(currentdata[1]);
console.log(currentdata[2]);
var datasets = [
{
label: "Current_Out",
data: currentdata[0],
yaxis: 2,
color: '#00C932',
points: { fillColor: "#00C932", show: true },
lines: { show: true }
}, {
label: "Temperature",
data: currentdata[1],
yaxis: 1,
color: "#0062FF",
points: { fillColor: "#0062FF", show: true },
lines: {show:true }
}]
var options = {
legend: {
show: true,
placement: 'outsideGrid',
container: $("#legend-container")
},
lines: {
show: true,
fill: false,
},
axisLabels: {
show: true
},
xaxes: [{
mode: "time",
timeformat: "%H:%M:%S",
axisLabel:'Date',
axisLabelUseCanvas: false,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
axisLabelPadding: 5
}],
yaxes: [{
position: "left",
axisLabel:'Celcius',
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
axisLabelPadding: 5
}, {
position: "right",
axisLabel: 'mA'
}],
grid: {
hoverable: true,
clickable: true,
borderWidth: 1
},
legend: {
labelBoxBorderColor: "none",
position: "right"
},
points: {
show: true,
fillColor: "#000000"
}
};
$.plot($("#placeholder"), datasets, options);
}
$.ajax({
url: '/Ajax/GetGraphData',
type: "GET",
dataType: "json",
success: onDataReceived,
failure: function() {
console.log('Fail!');
}
});
Jquery for Checkbox's
// insert checkboxes
var choiceContainer = $("#choices");
$.each(datasets, function (key, val) {
choiceContainer.append('<br/><input type="checkbox" name="' + key +
'" checked="checked" id="id' + key + '">' +
'<label for="id' + key + '">'
+ val.label + '</label>');
});
choiceContainer.find("input").click(plotAccordingToChoices);
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && datasets[key])
data.push(datasets[key]);
});
if (data.length > 0)
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 }
});
}
plotAccordingToChoices();
Scoping issue. var datasets is local to the onDataReceived function. It is not accessible outside that function. Initing it to null in the $(document).ready( handler should make it accessible to everything in that scope.
As for your second question, you need to show us the CSS attached to those divs. I'm guessing your graph-container is absoluting positioned. Also, in your options, you have two different configurations for legend. Delete the second one.

SetData() not working on Change Event HighCharts Pie Chart

I'm looking for a way to dynamically update data in a highcharts pie chart based on the change event on a dropdownlist. I have seen a couple examples but I am really unable to figure out why I can't get this working. Here is my whole code, I wrap my stuff inside a function so I can call the function with the Change() event of the dropdownlist, but I get the error of CRIPT438: Object doesn't support property or method 'setData'
function showClass(){
var total = 0;
var options = {
chart:{type:'pie',
renderTo: 'ctl00_ContentPlaceHolder1_Overview1_tcAssetAllocation_body',
events: {
load: function(event) {
$('.highcharts-legend-item').last().append('<br/><div style="width:220px"><hr/> <span style="float:left"> Total </span><span style="float:right">100%</span> </div>')
}
}
},
credits:{enabled: false},
colors:[
'#5485BC', '#AA8C30', '#5C9384', '#981A37', '#FCB319', '#86A033', '#614931', '#00526F', '#594266', '#cb6828', '#aaaaab', '#a89375'
],
title:{text: null},
tooltip:{
enabled: true,
animation: true
},
plotOptions: {
pie: {
allowPointSelect: true,
animation: true,
cursor: 'pointer',
showInLegend: true,
dataLabels: {
enabled: false,
formatter: function() {
return this.percentage.toFixed(2) + '%';
}
}
}
},
legend: {
enabled: true,
layout: 'vertical',
align: 'right',
width: 220,
verticalAlign: 'top',
borderWidth: 0,
useHTML: true,
labelFormatter: function() {
total += this.y;
return '<div style="width:200px"><span style="float:left">' + this.name + '</span><span style="float:right">' + this.y + '%</span></div>';
},
title: {
text: 'Primary',
style: {
fontWeight: 'bold'
}
}
},
series: [{
type: 'pie',
data: [['Domestic Equity', 38.5],['International Equity', 26.85],['Other', 15.70],['Cash and Equivalents', 10.48],['Fixed Income', 8.48]]
}]
}
var chart = new Highcharts.Chart(options);
$("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").change(function(){
var selVal = $("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").val();
if(selVal == '1124042'){
chart.series[0].setData([['Domestic Equity', 18.5], ['International Equity', 46.85], ['Other', 5.70], ['Cash and Equivalents', 20.48], ['Fixed Income', 8.48]]); }
});
}
is it because i am nested inside another function? it's jsut that all the fiddles use the document.ready function and it loads properly calling the function in the document.ready() but getting it on the change event is messing with me.
Any help is greatly appreciated.
Tahnk you very much,
NickG
You are wrong to use object options as part of Highcharts API. Find that line: options.series[0].setData and change to chart.series[0].setData(). Then remove creating new chart ( you don't need that - chart is already created ).

Categories