ntopng/httpdocs/js/sequence_sunburst.js
2017-03-07 05:06:26 +00:00

397 lines
12 KiB
JavaScript
Vendored

// Wrapper function
function do_sequence_sunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) {
var graph = new SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units);
graph.setInterval(window.setInterval(function(){graph.update();}, refresh));
// Return new class instance, with
return [graph];
}
function SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) {
// Add object properties like this
this.circle_name = circle_name;
this.sequence_name = sequence_name;
this.update_url = update_url;
this.url_params = url_params;
this.units = units;
this.refresh = refresh;
this.sunburstInterval;
var oldPieData = [];
var filteredPieData = [];
var rsp = create_sequence_sunburst(circle_name,sequence_name,title,units);
var color = rsp[0];
var partition = rsp[1];
var totalSize = rsp[2];
var arc = rsp[3];
var arc_group = rsp[4];
var trail = rsp[5];
var whiteCircle = rsp[6];
var totalLabel = rsp[7];
var totalValue = rsp[8];
var totalUnits = rsp[9];
var radius = rsp[10];
var width = rsp[11];
var height = rsp[12];
var b = rsp[13];
var last_process = "";
var last_byte = 0;
var substring_limit = 8;
// to run each time data is generated
this.update = function () {
$.ajax({
type: 'GET',
url: this.update_url,
data: this.url_params,
success: function(content) {
update_sequence_sunburst(jQuery.parseJSON(content));
},
error: function(content) {
console.log("error");
}
});
}
///////////////////////////////////////////////////////////
// STREAKER CONNECTION ////////////////////////////////////
///////////////////////////////////////////////////////////
// Needed to draw the pie immediately
this.update();
// var updateInterval = window.setInterval(update, refresh);
///////////////////////////////////////////////////////////
// UPDATE FUNCTIONS ////////////////////////////////////
///////////////////////////////////////////////////////////
this.flashUpdate = function (start,end) {
arc_group.selectAll("path").style("opacity", start)
.transition().duration(200).style("opacity", end);
}
function update_sequence_sunburst(data) {
streakerDataAdded = data;
// console.log(data);
oldPieData = filteredPieData;
pieData = partition.nodes(streakerDataAdded);
filteredPieData = pieData.filter(function(d) {
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
});
if((filteredPieData.length > 0) && (oldPieData.length > 0)) {
//REMOVE PLACEHOLDER CIRCLE
arc_group.selectAll("circle").remove();
arc_group.selectAll("path").remove();
// alert("Update");
}
paths = arc_group.selectAll("path").data(filteredPieData);
paths.enter().append("svg:path")
.attr("display", function(d) { return d.depth ? null : "none"; })
.attr("d", arc)
.attr("fill-rule", "evenodd")
.style("fill", function(d) { return color(d.name+d.id); })
.style("opacity", 1)
.on("mouseover", mouseover)
.on("dblclick",function(d) {if(d.url) window.location.href = d.url; });
// Add the mouseleave handler to the bounding circle.
d3.select("#container"+circle_name).on("mouseleave", mouseleave);
// Get total size of the tree = value of root node from partition.
totalSize = paths.node().__data__.value;
filteredPieData.forEach(function(d) {
if ((last_process.localeCompare(d.name) == 0) && (d.name != "")){
var data = bytesToVolumeAndLabel(d.value);
var value = data[0]
if (last_byte < d.value) {
value = data[0]+ ' \uf062';
}else if (last_byte > d.value) {
value = data[0]+ ' \uf063';
} else {
value = data[0]+ ' \uf068';
}
var name = d.name.substring(0,substring_limit);
if (d.name.length > substring_limit) {name = name + "..";}
totalValue.text(value);
totalLabel.text(name);
totalUnits.text(data[1]);
};
});
}
///////////////////////////////////////////////////////////
// UTILS FUNCTIONS ////////////////////////////////////
///////////////////////////////////////////////////////////
function mouseover(d) {
var percentage = (100 * d.value / totalSize).toPrecision(3);
var percentageString = percentage + "%";
if (percentage < 0.1) {
percentageString = "< 0.1%";
}
var data = bytesToVolumeAndLabel(d.value);
totalValue.text(data[0]);
totalLabel.text(d.name);
totalUnits.text(data[1]);
last_process = d.name;
last_byte = d.value;
var sequenceArray = getAncestors(d);
updateBreadcrumbs(sequenceArray, percentageString);
// Fade all the segments.
arc_group.selectAll("path")
.style("opacity", 0.3);
// Then highlight only those that are an ancestor of the current segment.
arc_group.selectAll("path")
.filter(function(node)
{
return (sequenceArray.indexOf(node) >= 0);
})
.style("opacity", 1);
};
// Restore everything to full opacity when moving off the visualization.
function mouseleave(d) {
// Hide the breadcrumb trail
trail.style("visibility", "hidden");
// Deactivate all segments during transition.
arc_group.selectAll("path").on("mouseover", null);
// Transition each segment to full opacity and then reactivate it.
arc_group.selectAll("path")
.transition()
.duration(500)
.style("opacity", 1)
.each("end", function() {
d3.select(this).on("mouseover", mouseover);
});
};
// Given a node in a partition layout, return an array of all of its ancestor
// nodes, highest first, but excluding the root.
function getAncestors(node) {
var path = [];
var current = node;
while (current.parent) {
path.unshift(current);
current = current.parent;
}
return path;
}
// Initialize the Breadcrumb as default
function initializeBreadcrumbTrail(circle_name,sequence_name) {
// Add the svg area.
var trail = d3.select("#"+sequence_name).append("svg:svg")
.attr("width", width)
.attr("height", 50)
.attr("id", "trail");
// Add the label at the end, for the percentage.
trail.append("svg:text")
.attr("id", "endlabel")
.style("fill", "#000");
return trail;
}
// Generate a string that describes the points of a breadcrumb polygon.
function breadcrumbPoints(d, i) {
var points = [];
points.push("0,0");
points.push(b.w + ",0");
points.push(b.w + b.t + "," + (b.h / 2));
points.push(b.w + "," + b.h);
points.push("0," + b.h);
if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
points.push(b.t + "," + (b.h / 2));
}
return points.join(" ");
}
// Update the breadcrumb trail to show the current sequence and percentage.
function updateBreadcrumbs(nodeArray, percentageString) {
// Data join; key function combines name and depth (= position in sequence).
var g = trail.selectAll("g")
.data(nodeArray, function(d) { return d.name + d.depth; });
// Add breadcrumb and label for entering nodes.
var entering = g.enter().append("svg:g");
entering.append("svg:polygon")
.attr("points", breadcrumbPoints)
.style("fill", function(d) { return color(d.name+d.id); });
entering.append("svg:text")
.attr("x", (b.w + b.t) / 2)
.attr("y", b.h / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(function(d)
{
var name = d.name.substring(0,substring_limit);
if (d.name.length > substring_limit) {name = name + "..";}
return (name);
});
// Set position for entering and updating nodes.
g.attr("transform", function(d, i) {
return "translate(" + i * (b.w + b.s) + ", 0)";
});
// Remove exiting nodes.
g.exit().remove();
// Now move and update the percentage at the end.
trail.select("#endlabel")
.attr("x", (nodeArray.length + 0.5) * (b.w + b.s))
.attr("y", b.h / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(percentageString);
// Make the breadcrumb trail visible, if it's hidden.
trail.style("visibility", "");
}
///////////////////////////////////////////////////////////
// INIT FUNCTIONS ////////////////////////////////////
///////////////////////////////////////////////////////////
function create_sequence_sunburst(circle_name, sequence_name,title,units) {
// Dimensions of sunburst.
var width = 600;
var height = 280;
var radius = 120;
// Total size of all segments; we set this later, after loading the data.
var totalSize = 0;
// Breadcrumb dimensions: width, height, spacing, width of tip/tail.
var b = {
w: 60, h: 25, s: 3, t: 10
};
//D3 helper function to create colors from an ordinal scale
var color = d3.scale.category20c();
var partition = d3.layout.partition()
.size([2 * Math.PI, radius * radius])
.value(function(d) { return d.size; });
var totalSize = 0;
//D3 helper function to draw arcs, populates parameter "d" in path object
var arc = d3.svg.arc()
.startAngle(function(d) { return d.x; })
.endAngle(function(d) { return d.x + d.dx; })
.innerRadius(function(d) { return Math.sqrt(d.y); })
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
var vis = d3.select("#"+circle_name).append("svg:svg")
.attr("width", width)
.attr("height", height);
var arc_group = vis.append("svg:g")
.attr("id", "container"+circle_name)
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
// Basic setup of page elements.
var trail = initializeBreadcrumbTrail(circle_name,sequence_name,width);
var whiteCircle = arc_group.append("svg:circle")
.attr("fill", "white")
.attr("r", radius);
// LABEL
totalLabel = arc_group.append("svg:text")
.attr("class", "label_sunburst")
.attr("dy", -25)
.attr("text-anchor", "middle")
.attr('font-family', 'FontAwesome')
.text("");
//PERCENT
totalValue = arc_group.append("svg:text")
.attr("class", "total")
.attr("dy", 7)
.attr("text-anchor", "middle")
.attr('font-family', 'FontAwesome')
.text("");
//UNITS LABEL
totalUnits = arc_group.append("svg:text")
.attr("class", "units")
.attr("dy",30)
.attr("text-anchor", "middle")
.text("");
return([color, partition, totalSize, arc, arc_group, trail, whiteCircle, totalLabel, totalValue, totalUnits, radius,width,height,b]);
} //End function create_sequence_sunburst
this.resetCentralCirleText = function (){
totalValue.text(" ");
totalLabel.text(" ");
totalUnits.text("");
}
}
///////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS ////////////////////////////////////
///////////////////////////////////////////////////////////
SequenceSunburst.prototype.setUrlParams = function(url_params) {
this.url_params = url_params;
this.resetCentralCirleText();
this.forceUpdate();
}
SequenceSunburst.prototype.forceUpdate = function(url_params) {
// this.stopInterval();
this.flashUpdate(0,1);
this.update();
// this.startInterval();
}
SequenceSunburst.prototype.setInterval = function(p_sunburstInterval) {
this.sunburstInterval = p_sunburstInterval;
}
SequenceSunburst.prototype.stopInterval = function() {
//disabled graph interval
window.clearInterval(this.sunburstInterval);
}
SequenceSunburst.prototype.startInterval = function() {
this.sunburstInterval = window.setInterval(this.update(), this.refresh)
}