tkyprof-0.0.6: julius/reports-id.julius
$(function() {
var data = #{json};
var parmalink = costCentreParmalink();
var chart = costCentreChart({
data: data,
parmalink: parmalink
});
var button = profilingModeButton({
chart: chart,
parmalink: parmalink
});
$(window).bind('popstate', function(event) {
console.log('popstate');
if (!window.history.ready && !event.originalEvent.state) {
return; // workaround for popstate on load
}
parmalink.popstate(location.pathname);
button.mode(parmalink.mode());
chart.mode(parmalink.mode());
chart.transposeById(parmalink.id());
});
});
function costCentreParmalink(spec) {
var that = {};
var parsed = parse(location.pathname),
prefix = parsed[1],
mode = parsed[2],
suffix = parsed[3];
function pathname() {
return prefix + mode + suffix;
};
function parse(path) {
var regex = /^(\/reports\/[0-9]+\/)(time|alloc)(.*)$/;
return regex.exec(path);
}
that.mode = function(newMode) {
if (!newMode)
return mode; // getter
mode = newMode;
window.history.ready = true; // workaround for popstate on load
history.pushState(null, null, pathname()); // HTML 5 History API
return mode;
};
that.transpose = function(node) {
var cursor = node, path = [];
for (cursor = node; cursor.parent; cursor = cursor.parent) {
path.unshift(cursor.no);
}
if (path.length > 0) {
suffix = "/" + path.join("/");
} else {
suffix = "";
}
};
that.popstate = function(url) {
var parsed = parse(url);
mode = parsed[2];
suffix = parsed[3];
};
that.id = function() {
var regex = /^.*\/([0-9]*)$/;
var matched = regex.exec(suffix);
return matched ? matched[1] : null;
};
that.pathname = pathname;
return that;
}
function profilingModeButton(spec) {
var that = {};
var chart = spec.chart, parmalink = spec.parmalink;
var timeButton = $("#time"),
allocButton = $("#alloc"),
_mode;
console.log(timeButton);
console.log(allocButton);
// methods
var mode = function(newMode) {
if (!newMode)
return _mode; // getter
console.log("button.mode: " + newMode);
_mode = newMode;
// buttons
if (_mode == "time") {
timeButton.addClass("active");
allocButton.removeClass("active");
} else {
timeButton.removeClass("active");
allocButton.addClass("active");
}
// chart
chart.mode(_mode);
return _mode;
};
// setup initial states and event handlers
mode(parmalink.mode());
timeButton.click(function(event) {
parmalink.mode("time");
mode(parmalink.mode());
});
allocButton.click(function(event) {
parmalink.mode("alloc");
mode(parmalink.mode());
});
// public slots
that.mode = mode;
return that;
}
function costCentreChart(spec) {
var that = {};
var cursor = spec.data,
selector = spec.selector,
parmalink = spec.parmalink;
var context = costCentreContext({cursor: cursor});
// chart
var chart = $("#chart"),
w = spec.w || chart.width(),
h = spec.h || chart.height(),
r = Math.min(w, h) / 2,
x = d3.scale.linear().range([0, 2*Math.PI]),
y = d3.scale.sqrt().range([0, r]),
color = spec.color || d3.scale.category20c();
var vis = d3.select("#chart")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")");
var partition = d3.layout.partition()
.children(function(d) { return d.subForest; })
.value(value(parmalink.mode()));
var arc = d3.svg.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2*Math.PI, x(d.x))); })
.endAngle(function(d) { return Math.max(0, Math.min(2*Math.PI, x(d.x + d.dx))); })
.innerRadius(function(d) { return Math.max(0, y(d.y)); })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
var path = vis.data([cursor]).selectAll("path")
.data(partition.nodes)
.enter().append("svg:path")
.attr("d", arc)
.attr("id", function(d) { return "cc" + d.no + (d.isParent ? "p" : ""); })
.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.on("click", click)
.on("mouseover", mouseover)
.each(function(d) { d.x0 = d.x; d.dx0 = d.dx; }); // stash the old values for transition
// event handlers
function click(d) {
transpose(d);
parmalink.transpose(d);
console.log(parmalink.pathname());
window.history.ready = true; // workaround for popstate on load
history.pushState(null, null, parmalink.pathname()); // HTML 5 History API
}
function mouseover(d) {
// XXX
}
// tweeners
function arcTween(a) {
var i = d3.interpolate({x: a.x0, dx: a.dx0}, a);
return function(t) {
var b = i(t);
a.x0 = b.x;
a.dx0 = b.dx;
return arc(b);
};
}
function zoomTween(d) {
var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, r]);
return function(d, i) {
return i
? function(t) { return arc(d); }
: function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
};
}
// helper functions
function value(mode) {
if (mode === "time")
return function(d) { return d.individualTime; };
else
return function(d) { return d.individualAlloc; };
}
function nodeFromId(id) {
if (!id)
return null;
console.log(id);
var elem = d3.select("#cc" + id);
console.log(elem);
return elem.node().__data__; // XXX: __data__ is not a public API
}
var mode = function(mode) {
path.data(partition.value(value(mode)))
.transition()
.duration(500)
.attrTween("d", arcTween);
};
var transpose = function(node) {
cursor = node;
context.transpose(cursor);
path.transition()
.duration(500)
.attrTween("d", zoomTween(cursor));
};
// setup initial states
mode(parmalink.mode());
transpose(nodeFromId(parmalink.id()) || spec.data);
// public slots
that.mode = mode;
that.transpose = transpose;
that.transposeById = function(id) {
transpose(nodeFromId(id) || spec.data);
};
return that;
}
function costCentreContext(spec) {
var that = {};
var cursor = spec.cursor;
var showCostCentre = function(node) {
var currentNode = $("#current-node dl");
$("#current-node-module", currentNode).text(node.module);
$("#current-node-name", currentNode).text(node.name);
$("#current-node-number", currentNode).text(node.no);
$("#current-node-entries", currentNode).text(node.entries);
$("#current-node-ind-time", currentNode).text(node.individualTime);
$("#current-node-ind-alloc", currentNode).text(node.individualAlloc);
$("#current-node-inh-time", currentNode).text(node.inheritedTime);
$("#current-node-inh-alloc", currentNode).text(node.inheritedAlloc);
};
var showChildren = function(node) {
$("#children ol li").remove();
var children = $("#children ol");
var cs = node.children;
if (cs) {
var n = cs.length < 10 ? cs.length : 10;
for (var i = 0; i < n; i++) {
children.append("<li>" + cs[i].name + "</li>");
}
}
};
// setup
showCostCentre(cursor);
showChildren(cursor);
// public slots
that.transpose = function(node) {
cursor = node;
showCostCentre(cursor);
showChildren(cursor);
};
return that;
}