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.
Related
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
jQuery json data is easily fetched from PHP without any issue. if i want to display same data with it is coming without any issue but js file is external file not embedded in html. so if i want to pass the value of jQuery var into JavaScript it is not working but it is working in same HTML file with id.
here is my jQuery external file
$(document).ready(function() {
(function() {
$('#upload-form2').ajaxForm({
dataType: 'json',
success: function(data) {
var html = '';
var sthtml = '';
var ndhtml = '',
downlo;
for (var i = 0; i < data.length; i++) {
z = i + 1;
downlo = data[i];
html += '<tr id="' + i + '"><td>' + z + '</td></tr>';
sthtml += '' + downlo.stchart + '';
ndhtml += '' + downlo.ndchart + '';
}
$('#down-btn').html(html);
$('#checkk').html(sthtml);
$('#chek').html(ndhtml);
$('#saving-details').html(html);
}
})
})();
});
if i am padding checkk and chek id to data is correctly being displayed data is { x: 1, y: 59 },{ x: 2, y: 93 },{ x: 3, y: 477 },{ x: 4, y: 506 }
but when i try to pass the same variable in datapoints of canvasjs nothing is coming.
i tried setting those sthtml and ndhtml as global variable by declaring before ready function.did not worked.
tried ''+sthtml+'' in datapoints did not work. tried canvasjs tutorial but they are passing external json file but i want to pass jquery var data as all data are already fetched correctly in jquery.
is there anyway i can add data to below datapoints other than i tried below. like but canvasjs will not accept this div in datapoints so some other way required
<script type="text/javascript">
window.onload = function() {
var sthtml = [];
var ndhtml = [];
var chart = new CanvasJS.Chart("chartContainer", {
axisY: {},
data: [{
dataPoints: [sthtml]
}, {
dataPoints: [ndhtml]
}],
legend: {
cursor: "pointer",
itemclick: function(e) {
chart.render();
}
}
});
chart.render();
}
</script>
it is not duplicate as the referred question did not identify the root cause even so its different
I wrote my code down to a small fiddle: http://jsfiddle.net/V8dyd/266/
I am able to render region labels as strings on the map but unable to render them as HTML.
$(function(){
var Jsondata = {
LK: " Region : Asia, Feedback : 228, Good : 34.00%, Normal : 33.00%, Bad : 30.00% ",
IN: "Total Responses : 228"
};
var map = $('#map').vectorMap({
map: 'world_mill_en',
zoomMin: 1,
zoomMax: 1,
regionLabelStyle: {
initial: {
fill: '#B90E32'
},
hover: {
fill: 'black'
}
},
labels: {
regions: {
render: function (code) {
if (code==="LK") {
var a = Jsondata[code];
var array = a.split(',');
var s = "<html><body><div><small>" + array[0] +"</small><br><small>" + array[1] + "</small><br><small>" + array[2] + "</small><br><small>" + array[3] + "</small></div</body></html>";
var htmlObject = document.createElement('div');
htmlObject.innerHTML = s;
return htmlObject;
// return s
}
}
}
}
});
});
The labels are rendered using svg TEXT-Tags and do not allow HTML.
In the current version this is not supported but i used a Hook in the Region Function for realize line breaks:
https://github.com/bjornd/jvectormap/blob/master/src/region.js
Like this:
jvm.Region = function(config){
var bbox,
text,
offsets,
labelDx,
labelDy;
this.config = config;
this.map = this.config.map;
this.shape = config.canvas.addPath({
d: config.path,
'data-code': config.code
}, config.style, config.canvas.rootElement);
this.shape.addClass('jvectormap-region jvectormap-element');
bbox = this.shape.getBBox();
myHook(bbox, text, offsets, config);
return false;
...
}
function myHook(bbox, text, offsets, config){
// Create your own Label like this
text = this.getLabelText(config.code);
if (this.config.label && text) {
offsets = this.getLabelOffsets(config.code);
this.labelX = bbox.x + bbox.width / 2 + offsets[0];
this.labelY = bbox.y + bbox.height / 2 + offsets[1];
this.label = config.canvas.addText({
text: text,
'text-anchor': 'middle',
'alignment-baseline': 'central',
x: this.labelX,
y: this.labelY,
'data-code': config.code
}, config.labelStyle, config.labelsGroup);
this.label.addClass('jvectormap-region jvectormap-element');
}
}
Thats not the best way but maybe it helps you!
I am using flot charts. I want to plot chart which is updated per second and also want to add the feature of turning off and on the data series.
I am able to make it work but has problems which I did not expect, like color of one series change when other series is turned off; other is when I update the array of data series the charts seems to move but it removes element from the right,at the same time the new value is plotted on the right hand side ...
var d1 = [] ;
var d2 = [] ;
var d3 = [] ;
$(function(){
{%for reading in readings%}
var time_stamp = parseFloat({{reading['timestamp']}} + 19800.00) * 1000
var A = parseFloat({{reading['values']['A']}}) ;
var V = parseFloat({{reading['values']['VLN']}}) - 50 ;
var W = parseFloat({{reading['values']['W']}}) / 1000 ;
d1.push([time_stamp,A]);
d2.push([time_stamp,V]);
d3.push([time_stamp,W]);
{%endfor%}
var datasets = {
"current":{
label : "A",
data : d1
},
"voltage":{
label : "V",
data : d2
},
"power":{
label : "W",
data : d3
},
}
var i = 0;
$.each(datasets, function(key, val) {
val.color = i;
++i;
});
// insert checkboxes
var choiceContainer = $("#choices");
$.each(datasets, function(key, val) {
choiceContainer.append("<br/><input type='checkbox' name='" + key +
"' checked='checked' id='id" + key + "'></input>" +
"<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, {
series: {
shadowSize: 0,
lines: {
show: true
},
},
yaxis: {
min: 0
},
xaxis: {
tickDecimals: 0,
mode:"time"
}
});
}
setTimeout(getNextDataset,1000);
}
plotAccordingToChoices();
});
function getNextDataset()
{
$.ajax({url : '/newdata' , success:function(result){
reading =JSON.parse(result);
var time_stamp = (parseFloat(reading.timestamp) + 19800.00) * 1000
var A = parseFloat(reading.values.A) ;
var W = parseFloat(reading.values.W) / 1000 ;
var V = parseFloat(reading.values.VLN) - 50 ;
d1.shift();d2.shift();d3.shift();
d1.push([time_stamp,A]);
d2.push([time_stamp,V]);
d3.push([time_stamp,W]);
var datasets = {
"current":{
label : "A",
data : d1
},
"voltage":{
label : "V",
data : d2
},
"power":{
label : "W",
data : d3
},
}
var data = [] ;
var choiceContainer = $("#choices");
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, {
series: {
shadowSize: 0,
lines: {
show: true
},
points:{
show:false
},
},
yaxis: {
min: 0
},
xaxis: {
tickDecimals: 0,
mode:"time"
}
});
}
}
});
setTimeout(getNextDataset,1000) ;
}
`
I am making use of code available in flot charts examples.Where am I going wrong ??
Thank you ?
Problem 1 : Color updating every time a checkbox was checked or unchecked
Reason: Every time the checkbox click event was triggered,some how the color used to get updated
Solution : Removed setTimeout(getNextDataset,1000); call from the function plotAccordingToChoices()
Problem 2: The data elements are removed from the right instead of left.
Reason : (Very dumb) Data was coming in descending order and I was using pushing data in that order only.So latest point was at location 0 of the array and oldest point was at location n-1.And I was removing (n-1)th point.
Solution : Replaced push in the beginning with unshift().Did the magic :P
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.