mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
New d3 charts are already done.
This commit is contained in:
@@ -141,10 +141,13 @@ class GraphicSet(object):
|
||||
return [graphic.display_name for graphic in self._graphics]
|
||||
|
||||
def export(self, rrdfile, start, end):
|
||||
return dict(
|
||||
(graph.display_name, graph.export(rrdfile, start, end))
|
||||
for graph in self.graphics
|
||||
)
|
||||
result = {}
|
||||
for graph in self.graphics:
|
||||
result[graph.display_name] = {
|
||||
"title": graph.title.encode("utf-8"),
|
||||
"curves": graph.export(rrdfile, start, end)
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
class MailTraffic(GraphicSet):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,43 +1,28 @@
|
||||
/*svg {
|
||||
width: 100%;
|
||||
}*/
|
||||
|
||||
.chart {
|
||||
position: relative;
|
||||
/*margin-bottom: 10px;
|
||||
padding-right: 40px;*/
|
||||
}
|
||||
|
||||
/*.legend {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0px;
|
||||
background-color: transparent;
|
||||
color: #404040;
|
||||
}*/
|
||||
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
top: 60px;
|
||||
display: none;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.grid .tick {
|
||||
stroke: lightgrey;
|
||||
opacity: 0.7;
|
||||
stroke: darkgrey;
|
||||
stroke-dasharray: 1, 2;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.grid path {
|
||||
stroke-width: 0;
|
||||
}
|
||||
|
||||
.line_over {
|
||||
stroke: gray;
|
||||
stroke: darkgrey;
|
||||
stroke-width: 1.5px;
|
||||
stroke-dasharray: 5, 5;
|
||||
stroke-dasharray: 1, 2;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.axis {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
.axis path,
|
||||
.axis line {
|
||||
fill: none;
|
||||
@@ -50,23 +35,27 @@
|
||||
}
|
||||
|
||||
.brush .extent {
|
||||
stroke: #fff;
|
||||
fill-opacity: .125;
|
||||
shape-rendering: crispEdges;
|
||||
stroke: #fff;
|
||||
fill-opacity: .125;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.legend rect {
|
||||
fill: none;
|
||||
stroke: black;
|
||||
opacity: 0;
|
||||
fill: none;
|
||||
stroke: black;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 0.9em;
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
top: 60px;
|
||||
display: none;
|
||||
font-size: 0.9em;
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.tip p {
|
||||
|
||||
@@ -1,99 +1,305 @@
|
||||
var Graphic = function(data, options) {
|
||||
this.initialize(data, options);
|
||||
/*
|
||||
*
|
||||
*/
|
||||
var Graphic = function(selector, data, options) {
|
||||
this.initialize(selector, data, options);
|
||||
};
|
||||
|
||||
Graphic.prototype = {
|
||||
constructor: Graphic,
|
||||
|
||||
defaults: {
|
||||
|
||||
height: 300,
|
||||
preview_height: 80,
|
||||
brush_height: 7,
|
||||
margin: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
bottom: 20
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function(data, options) {
|
||||
initialize: function(selector, data, options) {
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.graphics = {};
|
||||
this.setup(data);
|
||||
$(window).resize($.proxy(this.resize_graphics, this));
|
||||
this.selector = selector;
|
||||
this.data = data;
|
||||
$(window).resize($.proxy(this.resize, this));
|
||||
this.render();
|
||||
},
|
||||
|
||||
setup: function(data) {
|
||||
$.each(data.graphs, $.proxy(function(id, graph) {
|
||||
var chart = new Rickshaw.Graph({
|
||||
element: document.getElementById(id),
|
||||
renderer: 'area',
|
||||
stroke: true,
|
||||
series: graph,
|
||||
height: 350
|
||||
});
|
||||
|
||||
var preview = new Rickshaw.Graph.RangeSlider.Preview({
|
||||
graph: chart,
|
||||
element: document.getElementById(id + '_preview')
|
||||
});
|
||||
|
||||
var xAxis = new Rickshaw.Graph.Axis.Time({
|
||||
graph: chart,
|
||||
ticksTreatment: 'glow'
|
||||
});
|
||||
|
||||
var yAxis = new Rickshaw.Graph.Axis.Y({
|
||||
graph: chart
|
||||
});
|
||||
|
||||
var previewXAxis = new Rickshaw.Graph.Axis.Time({
|
||||
graph: preview.previews[0],
|
||||
/*timeFixture: new Rickshaw.Fixtures.Time.Local(),*/
|
||||
ticksTreatment: 'glow'
|
||||
});
|
||||
|
||||
var hoverDetail = new Rickshaw.Graph.HoverDetail( {
|
||||
graph: chart,
|
||||
xFormatter: function(x) {
|
||||
return new Date(x * 1000).toString();
|
||||
}
|
||||
});
|
||||
|
||||
var legend = new Rickshaw.Graph.Legend({
|
||||
graph: chart,
|
||||
element: document.getElementById(id + '_legend')
|
||||
});
|
||||
|
||||
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
|
||||
graph: chart,
|
||||
legend: legend
|
||||
});
|
||||
|
||||
chart.render();
|
||||
xAxis.render();
|
||||
yAxis.render();
|
||||
previewXAxis.render();
|
||||
|
||||
this.graphics[id] = {
|
||||
chart: chart, preview: preview
|
||||
};
|
||||
}, this));
|
||||
resize: function() {
|
||||
this.remove();
|
||||
this.render();
|
||||
},
|
||||
|
||||
resize_graphics: function(e) {
|
||||
$.each(this.graphics, function(id, graphic) {
|
||||
var w = $('#' + id).parent().width();
|
||||
$.each(graphic, function(id, object) {
|
||||
object.configure({width: w});
|
||||
object.render();
|
||||
});
|
||||
});
|
||||
remove: function() {
|
||||
this.container.select("svg").remove();
|
||||
$(this.container[0][0]).empty();
|
||||
},
|
||||
|
||||
update: function(data) {
|
||||
$.each(data.graphs, $.proxy(function(id, graph) {
|
||||
var $parent = $('#' + id).parent();
|
||||
$('#' + id).remove();
|
||||
$('#' + id + '_legend').remove();
|
||||
$('#' + id + '_preview').remove();
|
||||
$parent.append($("<div />", {id: id}));
|
||||
$parent.append($("<div />", {id: id + '_preview'}));
|
||||
$parent.append($("<div />", {id: id + '_legend', 'class': 'legend'}));
|
||||
}, this));
|
||||
this.setup(data);
|
||||
height: function() {
|
||||
return this.options.height + 2 * this.options.margin.top
|
||||
+ 2 * this.options.margin.bottom + this.options.preview_height
|
||||
+ this.options.brush_height;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var $element = $(this.selector);
|
||||
var width = $element.width();
|
||||
this.container = d3.select(this.selector)
|
||||
.append("div")
|
||||
.attr("class", "chart");
|
||||
this.container.append("h6")
|
||||
.html(this.data.title);
|
||||
var svg = this.container
|
||||
.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", this.height());
|
||||
|
||||
svg.append("defs").append("clipPath")
|
||||
.attr("id", "clip")
|
||||
.append("rect")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height + 30);
|
||||
|
||||
var x = d3.time.scale().range([0, width - 2 * this.options.margin.left]),
|
||||
x2 = d3.time.scale().range([0, width - 2 * this.options.margin.left]);
|
||||
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
|
||||
xAxis2 = d3.svg.axis().scale(x2).orient("bottom");
|
||||
var y = d3.scale.linear().range([this.options.height, 0]),
|
||||
y2 = d3.scale.linear().range([this.options.preview_height, 0]);
|
||||
var bisectDate = d3.bisector(function(d) { return d.x * 1000; }).left;
|
||||
|
||||
var brush = d3.svg.brush()
|
||||
.x(x2)
|
||||
.on("brush", brushed);
|
||||
|
||||
var points = [];
|
||||
|
||||
x.domain(d3.extent(this.data.curves[0].data.map(function(d) { return d.x * 1000; })));
|
||||
y.domain([
|
||||
d3.min(this.data.curves, function(d) { return d3.min(d.data, function(v) { return v.y; }); }),
|
||||
d3.max(this.data.curves, function(d) { return d3.max(d.data, function(v) { return v.y; }); })
|
||||
]);
|
||||
x2.domain(x.domain());
|
||||
y2.domain(y.domain());
|
||||
|
||||
var yAxis = d3.svg.axis().scale(y).orient("left");
|
||||
|
||||
var area = d3.svg.area()
|
||||
.interpolate("monotone")
|
||||
.x(function(d) { return x(d.x * 1000); })
|
||||
.y0(this.options.height)
|
||||
.y1(function(d) { return y(d.y); });
|
||||
|
||||
var area2 = d3.svg.area()
|
||||
.interpolate("monotone")
|
||||
.x(function(d) { return x2(d.x * 1000); })
|
||||
.y0(this.options.preview_height)
|
||||
.y1(function(d) { return y2(d.y); });
|
||||
|
||||
var focus = svg.append("g")
|
||||
.attr("class", "focus")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height)
|
||||
.attr("pointer-events", "all")
|
||||
.attr("transform",
|
||||
"translate(" + this.options.margin.left + ",0)");
|
||||
|
||||
var context = svg.append("g")
|
||||
.attr("class", "context")
|
||||
.attr("transform", "translate(" + this.options.margin.left + "," + (this.options.height + this.options.margin.top + this.options.margin.bottom + this.options.brush_height) + ")");
|
||||
|
||||
var curve2 = context.selectAll(".curve")
|
||||
.data(this.data.curves)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
|
||||
var curvegroup = focus.append("g")
|
||||
.attr('clip-path', 'url(#clip)');
|
||||
|
||||
var curve = curvegroup.selectAll(".curve")
|
||||
.data(this.data.curves)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
|
||||
var line = focus.append("line")
|
||||
.attr("class", "line_over")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", 0)
|
||||
.attr("y2", this.options.height);
|
||||
|
||||
var rect = focus.append("rect")
|
||||
.attr("fill", "none")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height);
|
||||
|
||||
var tooltip = this.container
|
||||
.append("div")
|
||||
.attr("class", "remove")
|
||||
.attr("class", "tip");
|
||||
|
||||
var path = curve.append("path")
|
||||
.attr("class", "area")
|
||||
.attr("d", function(d, i) {
|
||||
var path = this;
|
||||
|
||||
points[path] = {};
|
||||
d.data.forEach(function(d) {
|
||||
points[path][d.x] = d.y;
|
||||
});
|
||||
focus.append("circle")
|
||||
.attr("class", "tracker tracker-" + i)
|
||||
.attr("r", 4);
|
||||
return area(d.data);
|
||||
})
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
function make_x_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(6)
|
||||
.tickSize(-this.options.height, 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(6)
|
||||
.tickSize(-(width - 2 * this.options.margin.left), 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
var xrules = make_x_axis.apply(this);
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + (this.options.height) + ")")
|
||||
.call(xrules);
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis.apply(this));
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + this.options.height + ")")
|
||||
.call(xAxis);
|
||||
focus.append("g")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis);
|
||||
|
||||
var data = this.data.curves;
|
||||
rect
|
||||
.on("mouseover", function(d) {
|
||||
line.style("display", "block");
|
||||
tooltip.style("display", "block");
|
||||
data.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
focus.select(".tracker-" + cid).style("display", "block");
|
||||
});
|
||||
})
|
||||
.on("mousemove", function(d) {
|
||||
var mousex = d3.mouse(this)[0],
|
||||
mousey = d3.mouse(this)[1];
|
||||
var date = x.invert(mousex);
|
||||
var text = "";
|
||||
|
||||
line.attr("x1", mousex)
|
||||
.attr("x2", mousex);
|
||||
|
||||
data.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
var i = bisectDate(d.data, date.getTime(), 1),
|
||||
d0 = d.data[i - 1],
|
||||
d1 = d.data[i],
|
||||
point = date.getTime() - (d0.x * 1000) > (d1.x * 1000) - date.getTime() ? d1 : d0;
|
||||
text += "<p>" + d.name + ": " + point.y.toFixed(3) + "</p>";
|
||||
|
||||
var tracker_x = x(point.x * 1000),
|
||||
tracker_y = y(point.y);
|
||||
|
||||
focus.selectAll(".tracker-" + cid)
|
||||
.style("fill", d.color)
|
||||
.attr("cx", tracker_x)
|
||||
.attr("cy", tracker_y);
|
||||
});
|
||||
if (mousex + tooltip[0][0].clientWidth >= width - 2 * 40) {
|
||||
tooltip
|
||||
.style("left", (mousex - (tooltip[0][0].clientWidth - 30)) + "px");
|
||||
} else {
|
||||
tooltip.style("left", (mousex + 60) + "px");
|
||||
}
|
||||
tooltip.html("<p>" + date + "</p>" + text);
|
||||
})
|
||||
.on("mouseout", function(d) {
|
||||
tooltip.style("display", "none");
|
||||
line.style("display", "none");
|
||||
focus.selectAll(".tracker").style("display", "none");
|
||||
});
|
||||
|
||||
var legend = focus.append("g")
|
||||
.attr("class", "legend")
|
||||
.attr("transform", "translate(50,10)")
|
||||
.style("font-size", "12px")
|
||||
.call(d3.legend);
|
||||
|
||||
curve2.append("path")
|
||||
.attr("class", "area2")
|
||||
.attr("d", function(d) { return area2(d.data); })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + this.options.preview_height + ")")
|
||||
.call(xAxis2);
|
||||
|
||||
function make_preview_x_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(x2)
|
||||
.orient("bottom")
|
||||
.ticks(6)
|
||||
.tickSize(-this.options.preview_height, 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + (this.options.preview_height) + ")")
|
||||
.call(make_preview_x_axis.apply(this));
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x brush")
|
||||
.call(brush)
|
||||
.selectAll("rect")
|
||||
.attr("y", -6)
|
||||
.attr("height", this.options.preview_height + this.options.brush_height);
|
||||
|
||||
function brushed() {
|
||||
x.domain(brush.empty() ? x2.domain() : brush.extent());
|
||||
focus.selectAll(".area")
|
||||
.attr("d", function(d) { return area(d.data); });
|
||||
focus.select(".x.axis").call(xAxis);
|
||||
focus.select(".grid").call(xrules);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
var Graphic = function(selector, options) {
|
||||
this.initialize(selector, options);
|
||||
};
|
||||
|
||||
Graphic.prototype = {
|
||||
constructor: Graphic,
|
||||
|
||||
defaults: {
|
||||
height: 300,
|
||||
preview_height: 80,
|
||||
brush_height: 7,
|
||||
margin: {
|
||||
left: 40,
|
||||
top: 10,
|
||||
bottom: 20
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function(selector, data, options) {
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.selector = selector;
|
||||
this.data = data;
|
||||
$(window).resize($.proxy(this.resize, this));
|
||||
this.render();
|
||||
},
|
||||
|
||||
resize: function() {
|
||||
d3.selectAll("svg").remove();
|
||||
this.render();
|
||||
},
|
||||
|
||||
height: function() {
|
||||
return this.options.height + 2 * this.options.margin.top
|
||||
+ 2 * this.options.margin.bottom + this.options.preview_height
|
||||
+ this.options.brush_height;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var $element = $(this.selector);
|
||||
var width = $element.width();
|
||||
var container = d3.select(this.selector)
|
||||
.append("div")
|
||||
.attr("class", "chart");
|
||||
var svg = container
|
||||
.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", this.height());
|
||||
|
||||
svg.append("defs").append("clipPath")
|
||||
.attr("id", "clip")
|
||||
.append("rect")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height);
|
||||
|
||||
var x = d3.time.scale().range([0, width - 2 * this.options.margin.left]),
|
||||
x2 = d3.time.scale().range([0, width - 2 * this.options.margin.left]);
|
||||
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
|
||||
xAxis2 = d3.svg.axis().scale(x2).orient("bottom");
|
||||
var y = d3.scale.linear().range([this.options.height, 0]),
|
||||
y2 = d3.scale.linear().range([this.options.preview_height, 0]);
|
||||
var bisectDate = d3.bisector(function(d) { return d.x * 1000; }).left;
|
||||
|
||||
var brush = d3.svg.brush()
|
||||
.x(x2)
|
||||
.on("brush", brushed);
|
||||
|
||||
var points = [];
|
||||
|
||||
x.domain(d3.extent(this.data[0].data.map(function(d) { return d.x * 1000; })));
|
||||
y.domain([
|
||||
d3.min(this.data, function(d) { return d3.min(d.data, function(v) { return v.y; }); }),
|
||||
d3.max(this.data, function(d) { return d3.max(d.data, function(v) { return v.y; }); })
|
||||
]);
|
||||
x2.domain(x.domain());
|
||||
y2.domain(y.domain());
|
||||
|
||||
var yAxis = d3.svg.axis().scale(y).orient("left");
|
||||
|
||||
var area = d3.svg.area()
|
||||
.interpolate("cardinal")
|
||||
.x(function(d) { return x(d.x * 1000); })
|
||||
.y0(this.options.height)
|
||||
.y1(function(d) { return y(d.y); });
|
||||
|
||||
var area2 = d3.svg.area()
|
||||
.interpolate("cardinal")
|
||||
.x(function(d) { return x2(d.x * 1000); })
|
||||
.y0(this.options.preview_height)
|
||||
.y1(function(d) { return y2(d.y); });
|
||||
|
||||
var focus = svg.append("g")
|
||||
.attr("class", "focus")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height)
|
||||
.attr("pointer-events", "all")
|
||||
.attr("transform",
|
||||
"translate(" + this.options.margin.left + ",0)");// + this.options.margin.top * 2 + ")");
|
||||
|
||||
var context = svg.append("g")
|
||||
.attr("class", "context")
|
||||
.attr("transform", "translate(" + this.options.margin.left + "," + (this.options.height + this.options.margin.top + this.options.margin.bottom + this.options.brush_height) + ")");
|
||||
|
||||
var curve2 = context.selectAll(".curve")
|
||||
.data(this.data)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
|
||||
var curvegroup = focus.append("g")
|
||||
.attr('clip-path', 'url(#clip)');
|
||||
|
||||
var curve = curvegroup.selectAll(".curve")
|
||||
.data(this.data)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
|
||||
var line = focus.append("line")
|
||||
.attr("class", "line_over")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", 0)
|
||||
.attr("y2", 300);
|
||||
|
||||
var rect = focus.append("rect")
|
||||
.attr("fill", "none")
|
||||
.attr("width", width - 2 * this.options.margin.left)
|
||||
.attr("height", this.options.height);
|
||||
|
||||
var tooltip = d3.select(".chart")
|
||||
.append("div")
|
||||
.attr("id", "tooltip")
|
||||
.attr("class", "remove")
|
||||
.attr("class", "tip");
|
||||
|
||||
var path = curve.append("path")
|
||||
.attr("class", "area")
|
||||
.attr("d", function(d, i) {
|
||||
var path = this;
|
||||
|
||||
points[path] = {};
|
||||
d.data.forEach(function(d) {
|
||||
points[path][d.x] = d.y;
|
||||
});
|
||||
focus.append("circle")
|
||||
.attr("class", "tracker tracker-" + i)
|
||||
.attr("r", 4);
|
||||
return area(d.data);
|
||||
})
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
function make_x_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(5)
|
||||
.tickSize(-this.options.height, 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(5)
|
||||
.tickSize(-(width - 2 * this.options.margin.left), 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + (this.options.height + this.options.margin.top) + ")")
|
||||
.call(make_x_axis.apply(this));
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis.apply(this));
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + this.options.height + ")")
|
||||
.call(xAxis);
|
||||
focus.append("g")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis);
|
||||
|
||||
var data = this.data;
|
||||
rect
|
||||
.on("mouseover", function(d) {
|
||||
line.style("display", "block");
|
||||
tooltip.style("display", "block");
|
||||
data.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
focus.select(".tracker-" + cid).style("display", "block");
|
||||
});
|
||||
})
|
||||
.on("mousemove", function(d) {
|
||||
var mousex = d3.mouse(this)[0],
|
||||
mousey = d3.mouse(this)[1];
|
||||
var date = x.invert(mousex);
|
||||
var element = document.getElementById("tooltip");
|
||||
var text = "";
|
||||
|
||||
line.attr("x1", mousex)
|
||||
.attr("x2", mousex);
|
||||
|
||||
data.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
var i = bisectDate(d.data, date.getTime(), 1),
|
||||
d0 = d.data[i - 1],
|
||||
d1 = d.data[i],
|
||||
point = date.getTime() - (d0.x * 1000) > (d1.x * 1000) - date.getTime() ? d1 : d0;
|
||||
text += "<p>" + d.name + ": " + point.y.toFixed(3) + "</p>";
|
||||
|
||||
var tracker_x = x(point.x * 1000),
|
||||
tracker_y = y(point.y);
|
||||
|
||||
focus.selectAll(".tracker-" + cid)
|
||||
.style("fill", d.color)
|
||||
.attr("cx", tracker_x)
|
||||
.attr("cy", tracker_y);
|
||||
});
|
||||
if (mousex + element.clientWidth >= width - 2 * 40) {
|
||||
tooltip
|
||||
.style("left", (mousex - (element.clientWidth - 30)) + "px");
|
||||
} else {
|
||||
tooltip.style("left", (mousex + 50) + "px");
|
||||
}
|
||||
tooltip.html("<p>" + date + "</p>" + text);
|
||||
})
|
||||
.on("mouseout", function(d) {
|
||||
tooltip.style("display", "none");
|
||||
line.style("display", "none");
|
||||
focus.selectAll(".tracker").style("display", "none");
|
||||
});
|
||||
|
||||
var legend = focus.append("g")
|
||||
.attr("class", "legend")
|
||||
.attr("transform", "translate(50,10)")
|
||||
.style("font-size", "12px")
|
||||
.call(d3.legend);
|
||||
|
||||
curve2.append("path")
|
||||
.attr("class", "area2")
|
||||
.attr("d", function(d) { return area2(d.data); })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + this.options.preview_height + ")")
|
||||
.call(xAxis2);
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x brush")
|
||||
.call(brush)
|
||||
.selectAll("rect")
|
||||
.attr("y", -6)
|
||||
.attr("height", this.options.preview_height + this.options.brush_height);
|
||||
|
||||
function brushed() {
|
||||
x.domain(brush.empty() ? x2.domain() : brush.extent());
|
||||
focus.selectAll(".area")
|
||||
.attr("d", function(d) { return area(d.data); });
|
||||
focus.select(".x.axis").call(xAxis);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
var GraphicSet = function(selector, data, options) {
|
||||
this.initialize(selector, data, options);
|
||||
};
|
||||
|
||||
GraphicSet.prototype = {
|
||||
constructor: GraphicSet,
|
||||
|
||||
initialize: function(selector, data, options) {
|
||||
var graph = new Graphic(selector, data.graphs.averagetraffic, options);
|
||||
}
|
||||
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -80,13 +80,17 @@ Stats.prototype = {
|
||||
},
|
||||
|
||||
graphs_cb: function(data) {
|
||||
this.graphicset = new GraphicSet("#gset", data);
|
||||
|
||||
/*if (this.graphic === undefined) {
|
||||
this.graphic = new Graphic(data, {});
|
||||
} else {
|
||||
this.graphic.update(data);
|
||||
}*/
|
||||
if (this.graphics !== undefined) {
|
||||
$.each(this.graphics, function(id, graphic) {
|
||||
graphic.remove();
|
||||
});
|
||||
}
|
||||
this.graphics = [];
|
||||
$.each(data.graphs, $.proxy(function(id, graphdef) {
|
||||
this.graphics.push(
|
||||
new Graphic("#gset", graphdef)
|
||||
);
|
||||
}, this));
|
||||
},
|
||||
|
||||
search_domain: function(value) {
|
||||
|
||||
Reference in New Issue
Block a user