Add another series to existing plot with flot - javascript

I need to know how I can easily add another series to an existing plot using Flot.
Here is how I currently plot a single series:
function sendQuery() {
var host_name = $('#hostNameInput').val();
var objectName = $('#objectNameSelect option:selected').text();
var instanceName = $('#instanceNameSelect option:selected').text();
var counterName = $('#counterNameSelect option:selected').text();
$.ajax({
beforeSend: function () {
$('#loading').show();
},
type: "GET",
url: "http://okcmondev102/cgi-bin/itor_PerfQuery.pl?machine=" + host_name + "&objectName=" + objectName + "&instanceName=" + instanceName + "&counterName=" + counterName,
dataType: "XML",
success: function (xml) {
var results = new Array();
var counter = 0;
var $xml = $.xmlDOM(xml);
$xml.find('DATA').each(function () {
results[counter] = new Array(2);
results[counter][0] = $(this).find('TIMESTAMP').text();
results[counter][1] = $(this).find('VALUE').text();
counter++;
});
plot = $.plot($("#resultsArea"), [{
data: results,
label: host_name
}], {
series: {
lines: {
show: true
}
},
xaxis: {
mode: "time",
timeformat: "%m/%d/%y %h:%S%P"
},
colors: ["#000099"],
crosshair: {
mode: "x"
},
grid: {
hoverable: true,
clickable: true
}
});

You can just add another results set:
// build two data sets
var dataset1 = new Array();
var dataset2 = new Array();
var $xml = $.xmlDOM(xml);
$xml.find('DATA').each(function(){
// use the time stamp for the x axis of both data sets
dataset1[counter][0] = $(this).find('TIMESTAMP').text();
dataset2[counter][0] = $(this).find('TIMESTAMP').text();
// use the different data values for the y axis
dataset1[counter][1] = $(this).find('VALUE1').text();
dataset2[counter][2] = $(this).find('VALUE2').text();
counter++;
});
// build the result array and push the two data sets in it
var results = new Array();
results.push({label: "label1", data: dataset1});
results.push({label: "label2", data: dataset2});
// display the results as before
plot = $.plot($("#resultsArea"), results, {
// your display options
});

At a high-level, the result of your call into itor_PerfQuery.pl will need to be extended to include the additional series data. You'll then want to make your "results" variable a multi-dimensional array to support the additional data and you'll need to update the current xml "find" loop which populates results accordingly. The remainder of the code should stay the same as flot should be able to plot the extended dataset. I think a review of the flot example will help you out. Best of luck.

Related

Converting a Json value from a string to an integer

I am trying to convert a JSON string into an integer so that I can use this data in a google chart. As of right now I can only get one set of data to be displayed in my chart.
Here is my JQUERY code:
$("#shotsandbigcc").click(function(){
//alert("Button works");
$("#shotsandbigcc_popup").toggle();
var integer = $("#shotsandbigcc").attr("name");
//alert("integer: " + integer);
$.ajax('includes/test.php', {
type: 'POST', // http method
data: {myData: integer},// data to submit
dataType: 'json',
success: function(response){
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawMultSeries);
function drawMultSeries() {
var len = response.length;
for(var i=0; i<len; i++){
var year = response[i].Year;
var ontarget = parseInt(response[i].Shots_on_Target);
var offtarget = parseInt(response[i].Shots_off_Target);
alert(ontarget);
}
alert(year);
var data = google.visualization.arrayToDataTable([
['Year', 'Shots on Target', 'Shots off Target'],
[year, ontarget, offtarget],
[year, ontarget, offtarget]
]);
var options = {
title: 'Shooting Accuracy',
chartArea: {width: '50%'},
hAxis: {
title: 'Amount of Shots',
minValue: 0
},
vAxis: {
title: 'Year'
}
};
var chart = new google.visualization.BarChart(document.getElementById('shotsandbigcc_chart'));
chart.draw(data, options);
}
}
});
});
The JSON data is in an array which has this format [{"Year":"2019/2020","Shots_on_Target":"302","Shots_off_Target":"578","Accuracy":"0.34"},{"Year":"2020/2021","Shots_on_Target":"74","Shots_off_Target":"93","Accuracy":"0.44"}]
If someone could tell me how I can display both 2019/2020 and 2020/2021 data to be displayed. I would be most grateful as right now only the 2020/2021 data is being displayed. Thank you.
For integet value part:
var ontarget = parseInt(response[i].Shots_on_Target);
For your data part:
var vizData = [];
vizData.push(['Year', 'Shots on Target', 'Shots off Target']);
for(var i=0; i<len; i++){
var year = response[i].Year;
var ontarget = parseInt(response[i].Shots_on_Target);
var offtarget = parseInt(response[i].Shots_off_Target);
vizData.push([year, ontarget, offtarget]);
alert(ontarget);
}
alert(year);
var data = google.visualization.arrayToDataTable(vizData);
explaination: since in the loop the values are getting updated in every iteration so, the 'year', 'ontarget' and 'offtarget' will have the latest values only. So on every iteration you have to store values so that they do not get overwritten. For that now this code is pushing in array in every iteration preserving the previous values. Which now you can use in the google.visualization function.
Happy Coding!

CanvasJS not properly rendering chart

I am using the following code to render an OHLC chart in CanvasJS:
<script>
var candleData = [];
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: 'Demo Stacker Candlestick Chart (Realtime)'
},
zoomEnabled: true,
axisY: {
includeZero: false,
title: 'Price',
prefix: '$'
},
axisX: {
interval: 1,
},
data: [{
type: 'ohlc',
dataPoints: candleData
}
]
});
function mapDataToPointObject(data) {
var dataPoints = [];
for(var i = 0; i < data.length; i++) {
var obj = data[i];
var newObj = {
x: new Date(obj.time),
y: [
obj.open,
obj.high,
obj.low,
obj.close
]
}
dataPoints.push(newObj);
}
return dataPoints;
}
function updateChart() {
$.ajax({
url: 'http://localhost:8080',
success: function(data) {
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
chart.render();
}
});
}
$(function(){
setInterval(() => {
updateChart();
}, 500);
});
The data properly loads, parses into the correct format, and render() is called on the interval like it should. The problem is, while the chart axes and titles all render properly, no data shows up. The chart is empty.
What DOES work is setting the data directly to the chart using
chart.options.data[0].dataPoints = candleData;
Why does my above solution not work then? Is there a way I can update the chart's dataPoints without having to hardcode a direct accessor to the chart's dataPoints?
It's related to JavaScript pass by value and pass by reference.
After execution of the following line.
dataPoints: candleData
dataPoints will refer to the current value of candleData. ie. dataPoints = [];
Now if you redefine candleData to any other value.
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
Then dataPoints won't be aware of this update and will still refer to the empty array (that you pointed earlier).
The following snippet will make it easy to understand
//pass by value
var a = "string1";
var b = a;
a = "string2";
alert("b is: " + b); //this will alert "string1"
//pass by reference
var c = { s: "string1" };
var d = c;
c.s = "string2";
alert("d.s is: " + d.s); //this will alert "string2"
For more, you can read about pass by value and pass by reference.
Javascript by reference vs. by value
Explaining Value vs. Reference in Javascript

Re-compile JSON data to make less rows

If I have a JSON result that has many rows, sometimes up to 100
Label:Part1 Value:1000
Label:Part2 Value:700
Label:Part3 Value:600
Label:Part4 Value:500
... and so on
I would like to change the data so that it lists the top 5 results as normal, but instead of listing the rest, it sums the value and changes the label to 'others'.
Example
Label:Part1 Value:1000
Label:Part2 Value:700
Label:Part3 Value:600
Label:Part4 Value:500
Label:Part5 Value:500
Label:other Value:25650
Is this possible to do in javascript, before I pass to a chart.js pie? Or is there a better method to achieve this?
Current code for pie
function chart1(branch, apitime){
$.ajax({
url: jsonpath' + apitime + branch,
dataType: 'jsonp',
success: function (response) {
console.log (response);
var datachart = response;
var ctx2 = document.getElementById("chart-area2").getContext("2d");
var myChart = new Chart(ctx2).Pie(datachart);
}
});
}
Data is sorted and I could change the SQL on the server to do this also, I just don't know what the correct method is to do that.
JSON example here http://pastebin.com/p3Y9mSX3
You can modify your data just before creating the chart.
var top6 = datachart.slice(0,5)
top6[5] = {
label: 'other',
value: datachart.slice(5).reduce(function(sum, data) {
return sum + data.value
}, 0)
}
var ctx2 = document.getElementById("chart-area2").getContext("2d");
var myChart = new Chart(ctx2).Pie(top6);
This can be made more general to get the top N entries
var getTopN = function(dataArray, n)
var tops = dataArray.slice(0, n)
tops[n] = {
label: 'other',
value: dataArray.slice(n).reduce(function(sum, data) {
return sum + data.value
}, 0)
}
return tops
}
var top5 = getTopN(datachart, 5)
var top10 = getTopN(datachart, 10)

How to display custom tooltips on line chart using Rickshaw Library

I am developing a realtime graph system which will display the memory usage at particular time using data from json file . I am using Rickshaw Library which accepts tool tip in numeric type else the hard coded value supplied as a property to graph .
I have a json object as :
[
{
"memory": 444.08203125,
"memoryInfo": {
"rss": 444.08203125,
"vsize": 1271.125
},
"cpu": 0.2,
"url": [
"/admin/company/approved"
],
"time": "2/12/2016, 10:42:09 AM"
},
...
...
]
I want to show in tool tip at particular time what was the url served by server so that i can get proper information like which route is consuming more memory.
I will share my so far js code with you so that it will be better to understand .
script.js
$(function(){
var json = null;
console.log("Document Ready");
$.ajax({
url: 'data.json',
type: 'get',
success: function (data) {
console.log("Got data");
json = data
drawGraph()
}
});
var interval = 250;
//function to use from populating new values to graph
var getMemory = function(index) {
return json[index].memory
}
var getUrl = function(index) {
return json[index].url[0]
}
var getToolTip = function(){
console.log("getting tooltip")
return "api/login"
}
var drawGraph = function(){
// instantiate our graph!
graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
width: 900,
height: 400,
renderer: 'line',
interpolate:'basis',
series: new Rickshaw.Series.FixedDuration([{ name: 'memory' ,color:'steelblue',tooltip:"/api/login"}], undefined, {
timeInterval: interval,
maxDataPoints: 500,
timeBase: new Date().getTime() / 1000,
})
})
//tooltip is hardcoded should be dynamic when fetching each object from json
graph.render();
// get Recent log data using socket and feed it to graph
var i = 0;
var iv = setInterval( function() {
i++
var data = { memory: getMemory(i)};
graph.series.addData(data);
graph.render();
}, interval );
//hover details
var hoverDetail = new Rickshaw.Graph.HoverDetail( {
graph: graph,
formatter: function(series, x, y) {
var date = '<span class="date">' + new Date(x * 1000).toUTCString() + '</span>';
var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
var content = swatch + series.tooltip + ": " + parseInt(y) + '<br>' + date;
console.log(series)
return content;
}
});
}
});//jQuery
Can you give us some further information regarding your problem/error?
From a quick look that I had, your tooltips (Rickshaw.Graph.HoverDetail) won't be able to render because you are asking in formatter for inputs "series,x,y" and you haven't set each element of the data array to have a x and y value.
example:
data: [ { x: 0, y: 5 }, { x: 1, y: 10 } ]
Take a look at rickshaw example here.

HighCharts Loading from CSV File with Many Data Points

After much searching and wanting to bang my head against my desk, I'm posting my first question on stackoverflow.
I've got an ASP.NET web application that is generating some data on the server side and creating a CSV file on the server.
I'm using HighCharts to produce a graph. Everything is working great, however, depending on what kind of date range a user runs there can be a few data points or many data points.
The problem comes in when there are many data points. Look at the X-Axis, and you'll see what I mean. Is there anyway to "group" these where it doesn't show every single point on the X-Axis?
The dates are at random intervals.
I've created a JSFiddle with my client side code and the contents of my CSV file in a JavaScript variable.
Here is my code:
function parseDate(dateStr) {
var matches = dateStr.match(/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/)
return Date.UTC(matches[3], matches[1]-1, matches[2]);
}
var csv = 'Chart,3/4/2007,3/24/2007,4/13/2007,4/25/2007,9/19/2007,9/28/2007,11/5/2007,1/7/2008,1/14/2008,1/21/2008,1/27/2008,2/3/2008,2/10/2008,2/17/2008,2/24/2008,3/2/2008,3/23/2008,3/30/2008,4/5/2008,4/21/2008,5/3/2008,5/10/2008,5/17/2008,5/24/2008,5/31/2008,6/8/2008,6/15/2008,6/29/2008,7/4/2008,7/18/2008,7/25/2008,8/1/2008,8/8/2008,9/17/2010,11/25/2010,8/16/2012,1/17/2013,1/27/2013\nDates,180.00,175.50,167.00,166.50,170.00,171.50,174.00,163.00,162.50,164.00,166.50,166.50,167.50,170.00,170.00,171.00,169.00,166.50,166.00,166.50,162.00,160.00,160.50,162.50,164.00,164.00,165.00,165.50,166.00,169.00,171.00,170.00,171.00,165.00,165.00,189.00,177.00,175.50';
var options = {
chart: {
renderTo: 'chart',
defaultSeriesType: 'line'
},
title: {
text: 'Test Chart'
},
xAxis: {
type: 'datetime',
categories: []
},
yAxis: {
title: {
text: 'Pounds'
}
},
series: []
};
// Split the lines
var lines = csv.split('\n');
$.each(lines, function(lineNo, line) {
var items = line.split(',');
if (lineNo == 0) {
$.each(items, function(itemNo, item) {
if (itemNo > 0) options.xAxis.categories.push(parseDate(item));
});
}
else {
var series = {
data: []
};
$.each(items, function(itemNo, item) {
if (itemNo == 0) {
series.name = item;
} else {
series.data.push(parseFloat(item));
}
});
options.series.push(series);
}
});
var chart = new Highcharts.Chart(options);
Here is the link to JSFiddle:
http://jsfiddle.net/Q2hyF/6/
Thanks in Advance,
Robert
Check out HighStocks and its DataGrouping feature:
http://www.highcharts.com/stock/demo/data-grouping
It can handle much larger datasets than HighCharts can. However, there are drawbacks as the newest HighCharts features are not always immediately in HighStocks. There are generally only minor changes needed to your syntax to use HighStocks, if you want to test it.
I ended up getting this working and never posted the answer... Here is the answer.
Take a close look at:
series.data.push([parseDate(points[0]), parseFloat(points[1])]);
in the code below...
function parseDate(dateStr) {
var matches = dateStr.match(/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/)
return Date.UTC(matches[3], matches[1] - 1, matches[2]);
}
var csv = 'Chart,11/1/2013|6,11/2/2013|4,11/3/2013|6,11/4/2013|3,11/5/2013|5,11/6/2013|5,11/7/2013|5,11/8/2013|6,11/9/2013|4,11/10/2013|13,11/11/2013|12,11/12/2013|3,11/13/2013|5,11/14/2013|7,11/15/2013|9,11/16/2013|0,11/17/2013|2,11/18/2013|3,11/19/2013|2,11/20/2013|16,11/21/2013|6,11/22/2013|9,11/23/2013|9,11/24/2013|20,11/25/2013|10,11/26/2013|10,11/27/2013|4,11/28/2013|9,11/29/2013|7,11/30/2013|7';
var options = {
chart: {
renderTo: 'chart',
type: 'line'
},
title: {
text: 'Sales'
},
xAxis: {
type: 'datetime'
},
series: []
};
var lines = csv.split('\n');
$.each(lines, function (lineNo, line) {
var items = line.split(',');
var series = {
data: []
};
$.each(items, function (itemNo, item) {
if (itemNo == 0) {
series.name = item;
} else {
var points = item.split('|');
series.data.push([parseDate(points[0]), parseFloat(points[1])]);
}
});
options.series.push(series);
});
var chart = new Highcharts.Chart(options);
http://jsfiddle.net/rswilley601/gtsLatyr/

Categories