Created
September 13, 2014 05:49
-
-
Save toni-moreno/c87d55144d7320b6fd7a to your computer and use it in GitHub Desktop.
highcharts.graphite.js ( Graphite viewer core based on highcharts )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//http://jsfiddle.net/Gv7Tg/27/ | |
var dashCtrl = { | |
onChart:[], // ch: , id: // | |
//graphite vars | |
data_mode: 0, //1=hicharts //0= graphite original | |
graphite_url: null, //null = current host | |
//zoom synchronization vars | |
controllingChart:null, | |
defaultTickInterval:5, | |
currentTickInterval:5, | |
//time refresh values | |
dashboard_refresh_time:0, | |
dashboard_refresh_margin:60, // seconds | |
rf_time:0, | |
/* | |
* update time | |
*/ | |
updateIncrementTime: function() { | |
var rf_time_ms=new Date().getTime() - this.dashboard_refresh_time; | |
this.rf_time=parseInt((rf_time_ms+500)/1000)+ this.dashboard_refresh_margin; | |
}, | |
/* | |
* update time | |
*/ | |
updateLastRefreshTime: function () { | |
this.dashboard_refresh_time=new Date().getTime(); | |
}, | |
/* | |
* Initialize highcharts | |
*/ | |
init: function(graphite_url,mode) { | |
this.graphite_url = graphite_url || null; | |
this.data_mode = mode || 0; | |
Highcharts.setOptions({ | |
global: { useUTC: false }, | |
chart: { | |
style: { | |
fontFamily: 'monospace' | |
} | |
} | |
}); | |
}, | |
/* | |
* syncronizeCrossHairs | |
*/ | |
resetCharts:function() { | |
this.onChart = []; | |
}, | |
/* | |
* syncronizeCrossHairs | |
*/ | |
unzoom: function() { | |
for (var i=0; i < this.onChart.length; i++) { | |
this.onChart[i].ch.options.chart.isZoomed = false; | |
this.onChart[i].ch.xAxis[0].setExtremes(null, null); | |
} | |
}, | |
/* | |
* syncronizeCrossHairs | |
*/ | |
syncronizeCrossHairs: function (chart) { | |
var container = $(chart.container), | |
offset = container.offset(), | |
x, y, isInside, report; | |
container.mousemove(function(evt) { | |
x = evt.clientX - chart.plotLeft - offset.left; | |
y = evt.clientY - chart.plotTop - offset.top; | |
var xAxis = chart.xAxis[0]; | |
//remove old plot line and draw new plot line (crosshair) for this chart | |
for (var i=0; i < dashCtrl.onChart.length; i++) { | |
var xAxis1 = dashCtrl.onChart[i].ch.xAxis[0]; | |
xAxis1.removePlotLine("myPlotLineId"); | |
xAxis1.addPlotLine({ | |
value: chart.xAxis[0].translate(x, true), | |
width: 1, | |
color: 'red', | |
//dashStyle: 'dash', | |
id: "myPlotLineId" | |
}); | |
} | |
//if you have other charts that need to be syncronized - update their crosshair (plot line) in the same way in this function. | |
}); | |
}, | |
/*compute a reasonable tick interval given the zoom range - | |
*have to compute this since we set the tickIntervals in order | |
*to get predictable synchronization between 3 charts with | |
*different data. | |
*/ | |
computeTickInterval:function (xMin, xMax) { | |
var zoomRange = xMax - xMin; | |
if (zoomRange <= 2) | |
this.currentTickInterval = 0.5; | |
if (zoomRange < 20) | |
currentTickInterval = 1; | |
else if (zoomRange < 100) | |
this.currentTickInterval = 5; | |
}, | |
/* | |
*explicitly set the tickInterval for the all charts - based on | |
*selected range | |
*/ | |
setTickInterval: function (event) { | |
var xMin = event.xAxis[0].min; | |
var xMax = event.xAxis[0].max; | |
this.computeTickInterval(xMin, xMax); | |
for (var i=0; i < this.onChart.length; i++) { | |
this.onChart[i].ch.xAxis[0].options.tickInterval = this.currentTickInterval; | |
this.onChart[i].ch.xAxis[0].isDirty = true; | |
} | |
}, | |
/* | |
* hc_init_graph | |
http://graphite.readthedocs.org/en/latest/render_api.html | |
* addGraph(id,params) { | |
- title | |
- url | |
- areaAlpha | |
- areaMode | |
- bgcolor | |
- colorList | |
- fgcolor | |
- fontBold | |
- fontItalic | |
- fontName | |
- fontSize | |
- graphOnly ( no grid , axes, legend) | |
- graphType ( line, pie) | |
- hideLegend | |
- hideAxes | |
- hideYAxis | |
- hideGrid | |
- leftColor(Dual Y axis) | |
- leftDashed(Dual Y axix) | |
- leftWidth | |
- lineMode (slope,staircase,connected) | |
- lineWidth | |
- logBase | |
- margin | |
- yMax | |
- yMin | |
-minorGridLineColor | |
} | |
*/ | |
addChart: function (id,title,type) { | |
var char_type= type || 'line'; | |
var c_chart=new Highcharts.Chart({ | |
title:{ | |
text: title, | |
x: -20 | |
}, | |
chart:{ | |
renderTo: id, | |
type: char_type, | |
zoomType: 'x', | |
events: { | |
load: function() { | |
} | |
} | |
}, | |
xAxis:{ | |
minorTickInterval: 'auto', | |
type: 'datetime', | |
maxZoom: 1 * 1800000, //30 min | |
events:{ | |
afterSetExtremes:function(){ | |
if (!this.chart.options.chart.isZoomed) { | |
var xMin = this.chart.xAxis[0].min; | |
var xMax = this.chart.xAxis[0].max; | |
var zmRange = dashCtrl.computeTickInterval(xMin, xMax); | |
for(var i=0;i< dashCtrl.onChart.length;i++) { | |
dashCtrl.onChart[i].ch.xAxis[0].options.tickInterval =zmRange; | |
dashCtrl.onChart[i].ch.xAxis[0].isDirty = true; | |
if(dashCtrl.onChart[i].ch != this.chart ) { | |
dashCtrl.onChart[i].ch.options.chart.isZoomed = true; | |
dashCtrl.onChart[i].ch.xAxis[0].setExtremes(xMin, xMax, true); | |
dashCtrl.onChart[i].ch.options.chart.isZoomed = false; | |
} | |
} | |
} | |
} | |
} | |
}, | |
yAxis:{ | |
minorTickInterval: 'auto', | |
//min:0, | |
title: { | |
text: null | |
}, | |
labels: { | |
} | |
}, | |
tooltip:{ | |
crosshairs: true, | |
shared:true, | |
formatter: function() { | |
d1=new Date(this.x); | |
var s= '<b>'+ d1.toLocaleString() +'</b>'; | |
if(char_type == 'area') { | |
var sum = 0; | |
$.each(this.points, function(i, point) { | |
var v=parseFloat(point.y).toFixed(2); | |
var p=parseFloat(point.percentage).toFixed(2); | |
//Parse CactiStile | |
var cur_name=point.series.name; | |
var parts = cur_name.split(' '); | |
var real_name=parts[0]; | |
s += '<br/><span style="color:'+ point.series.color+'">\u25CF </span>'+ real_name +': <b>'+ v +':('+p+'%)</b>'; | |
sum = sum + point.y; | |
}); | |
s += '<br/>Total: '+parseFloat(sum).toFixed(2); | |
} else { | |
$.each(this.points, function(i, point) { | |
var v=parseFloat(point.y).toFixed(2); | |
//Parse CactiStile | |
var cur_name=point.series.name; | |
var parts = cur_name.split(' '); | |
var real_name=parts[0]; | |
s += '<br/><span style="color:'+ point.series.color+'">\u25CF </span>'+ real_name +': <b>'+ v +'</b>'; | |
}); | |
} | |
return s; | |
} | |
}, | |
legend: { | |
}, | |
plotOptions: { | |
series: { | |
marker: { | |
enabled: false | |
} | |
}, | |
area: { | |
stacking: 'normal', | |
} | |
}, | |
scrollbar: { | |
enabled: true | |
}/*, | |
exporting: { | |
buttons: { | |
customButton: { | |
x: -62, | |
onclick: function () { | |
alert('Clicked'); | |
}, | |
symbol: 'circle' | |
} | |
} | |
}*/ | |
},function(chart){ | |
//this function needs to be added to each syncronized chart | |
dashCtrl.syncronizeCrossHairs(chart); | |
}); | |
this.onChart.push({ | |
ch:c_chart, | |
id:id, | |
url: null | |
}); | |
}, | |
getIdFromIndex:function(index) { | |
return this.onChart[index].id; | |
}, | |
getIndexFromId:function(id) { | |
for(var i=0; i < this.onChart.length; i++) { | |
if(this.onChart[i].id == id ) return i; | |
} | |
}, | |
/* | |
* setChartData(index,) | |
*/ | |
setChartData: function(id,from,until,urlreq) { | |
var i; | |
if (typeof id === "string") { | |
i=this.getIndexFromId(id); | |
} else { | |
i=id; | |
} | |
var l_from = from || "-12h"; | |
if(until == "-" ) { | |
var l_until = '-'+this.dashboard_refresh_margin+'s'; | |
} else { | |
var l_until = until; | |
} | |
var chart=this.onChart[i].ch; | |
this.onChart[i].url=urlreq; | |
if(this.data_mode) subformat="&subformat=highcharts"; | |
else subformat=""; | |
var full_url='/render?format=json'+subformat+'&from='+l_from+'&until='+l_until+'&'+urlreq; | |
if(this.graphite_url != null ) full_url=this.graphite_url+full_url; | |
$.ajax({ | |
url: full_url, | |
type: 'GET', | |
dataType: 'json', | |
timeout: 60000, | |
async: false, | |
//async: true, | |
error: function (data, textStatus, jqXHR){ | |
alert('ERROR2:'+textStatus); | |
}, | |
success: function (data, textStatus, jqXHR){ | |
$.each(data,function(index){ | |
var title =this.target; | |
var timedata = this.datapoints; | |
if(dashCtrl.data_mode){ | |
//highcharts formatted | |
var timedata2=timedata; | |
} else { | |
//original graphite formatted | |
var timedata2= new Array(); | |
var n=this.datapoints.length; | |
var i=0; | |
for(i=0;i<n;i++){ | |
timedata2.push([timedata[i][1]*1000,timedata[i][0]]); | |
} | |
} | |
chart.addSeries({ | |
name: title, | |
lineWidth: 1, | |
radius:0, | |
data: timedata2 | |
}); | |
}); | |
} | |
}); | |
}, | |
/* | |
* updateData(id,urlreq) | |
* updateData(index) | |
*/ | |
updateChartData: function(id) { | |
var i; | |
if (typeof id === "string") { | |
i=this.getIndexFromId(id); | |
} else { | |
i=id; | |
} | |
if(this.data_mode) subformat="&subformat=highcharts"; | |
else subformat=""; | |
var chart=this.onChart[i].ch; | |
var urlreq=this.onChart[i].url; | |
var full_url='/render?format=json'+subformat+'&from=-'+this.rf_time+'s&until=-'+this.dashboard_refresh_margin+'s&'+urlreq; | |
if(this.graphite_url != null) full_url=this.graphite_url+full_url; | |
$.ajax({ | |
url: full_url, | |
type: 'GET', | |
dataType: 'json', | |
timeout: 60000, | |
/*async: false,*/ | |
async: true, | |
error: function (data, textStatus, jqXHR){ | |
alert('ERROR2:'+textStatus); | |
}, | |
success: function (data, textStatus, jqXHR){ | |
$.each(data,function(index){ | |
var title =this.target; | |
var timedata = this.datapoints; | |
//create new array to swap time,value order (value,timestamp)-> (timestamp*1000,value) | |
if(dashCtrl.data_mode){ | |
//highcharts formatted | |
var timedata2=timedata; | |
} else { | |
//original graphite formatted | |
var timedata2= new Array(); | |
var n=this.datapoints.length; | |
var i=0; | |
for(i=0;i<n;i++){ | |
timedata2.push([timedata[i][1]*1000,timedata[i][0]]); | |
} | |
} | |
for(var i=0;i<timedata2.length;i++) { | |
chart.series[index].addPoint(timedata2[i],false,true); | |
} | |
}); | |
chart.redraw(); | |
} | |
}); | |
}, | |
updateAllCharts: function() { | |
this.updateIncrementTime(); | |
for(var i=0; i < this.onChart.length; i++) { | |
this.updateChartData(i); | |
} | |
this.updateLastRefreshTime(); | |
}, | |
addLinkToChart: function(id,link,image) { | |
img=image || '/content/img/link.png' | |
var i; | |
if (typeof id === "string") { | |
i=this.getIndexFromId(id); | |
} else { | |
i=id; | |
} | |
var chart=this.onChart[i].ch; | |
chart.renderer.image(img, 5, 5, 20, 20) | |
.on('click', function() { | |
window.location.href = link | |
//location.href=xxx | |
}) | |
.css({ | |
cursor: 'pointer' | |
}) | |
.css({ | |
position: 'relative', | |
"margin-left": "-90px", | |
opacity: 0.75 | |
}) | |
.attr({ | |
zIndex: -100 | |
zIndex: -100 | |
}) | |
.add(); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment