309:c828dbfa7137
Anton Shestakov <av6@dwimlabs.net>, Tue, 03 Oct 2017 19:58:24 +0800
viewer: show tooltip for line chart

next change 311:cdd183a85dd1
previous change 308:9758f607f33c

static/candolint.js

Permissions: -rw-r--r--

Other formats: Feeds:
(function($) {
var humanizeTimestamps = function() {
$('time[datetime]').each(function() {
var $this = $(this);
$this.text(moment($this.attr('datetime')).fromNow());
});
};
humanizeTimestamps();
window.setInterval(humanizeTimestamps, 15 * 1000);
})(jQuery);
(function($) {
$('.check-log div.task').each(function() {
var $line = $(this);
var task = $line.attr('data-task');
var $lines = $line.nextAll('[data-task="' + task + '"]');
if ($lines.length === 0) { return; }
var $collapser = $('<a>').addClass('collapser');
$line.append($collapser);
var toggle = function() {
var collapsed = $collapser.hasClass('collapsed');
$lines.toggleClass('uk-hidden', collapsed);
};
$collapser.on('click', function() {
$collapser.toggleClass('collapsed');
toggle();
});
var important = '.error, .warning, .failure, :target';
if (task !== 'checks' && $lines.filter(important).length === 0) {
$collapser.addClass('collapsed');
toggle();
}
});
})(jQuery);
(function($, d3) {
if ($('#check-chart-data, #check-chart').length !== 2) { return; }
var data = JSON.parse($('#check-chart-data').text());
var $container = $('.chart-container');
var $tooltip = $container.find('.chart-tooltip');
var svg = d3.select('#check-chart');
var margin = {top: 10, right: 45, bottom: 30, left: 45};
var padding = 8;
var maxE = d3.max(data.points, function(d) { return d.errors; });
var maxW = d3.max(data.points, function(d) { return d.warnings; });
var maxD = d3.max(data.points, function(d) { return d.duration; });
var x = d3.scalePoint().domain(data.points.map(function(d) { return d.ordinal; }));
var y1 = d3.scaleLinear().domain([0, Math.max(maxE, maxW)]);
var y2 = d3.scaleLinear().domain([0, maxD]);
var formatDuration = function(d) {
return moment.utc(d, 'X').format('m:ss');
};
var config = [
{name: 'duration', color: '#00a8e6', scale: y2, format: formatDuration},
{name: 'warnings', color: '#faa732', scale: y1},
{name: 'errors', color: '#da314b', scale: y1}
];
var render = function() {
svg.attr('width', $container.width());
svg.attr('height', $container.height());
var width = +svg.attr('width') - margin.left - margin.right;
var height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var cg = g.append('g')
.attr('shape-rendering', 'crispEdges');
x.rangeRound([0, width]);
y1.rangeRound([height, 0]);
y2.rangeRound([height, 0]);
cg.append('line')
.attr('stroke', '#000')
.attr('stroke-dasharray', '5,2')
.attr('x1', x(data.current) + 0.5)
.attr('y1', 0)
.attr('x2', x(data.current) + 0.5)
.attr('y2', height);
var hover = cg.append('line')
.attr('opacity', 0)
.attr('stroke', '#000')
.attr('y1', 0)
.attr('y2', height);
cg.append('g')
.attr('transform', 'translate(0,' + (height + padding) + ')')
.call(d3.axisBottom(x));
cg.append('g')
.attr('transform', 'translate(' + (-padding) + ',0)')
.call(d3.axisLeft(y1).ticks(5));
cg.append('g')
.attr('transform', 'translate(' + (width + padding) + ',0)')
.call(d3.axisRight(y2).ticks(5).tickFormat(formatDuration));
$.each(config, function(i, series) {
var sg = g.append('g')
.attr('fill', series.color)
.attr('stroke', 'white')
.attr('stroke-width', 2);
var line = d3.line()
.defined(function(d) { return d[series.name] !== null; })
.x(function(d) { return x(d.ordinal); })
.y(function(d) { return series.scale(d[series.name]); });
sg.append('path')
.datum(data.points)
.attr('fill', 'none')
.attr('stroke', series.color)
.attr('d', line);
sg.selectAll('circle')
.data(data.points)
.enter()
.filter(function(d) { return d[series.name] !== null; })
.append('circle')
.attr('r', 5)
.attr('cx', function(d) { return x(d.ordinal); })
.attr('cy', function(d) { return series.scale(d[series.name]); });
});
var rectW = x.step();
g.append('g')
.attr('fill-opacity', 0)
.selectAll('a')
.data(data.points)
.enter()
.append('a')
.attr('href', function(d) { return data.projectURL + '/' + d.ordinal; })
.append('rect')
.attr('x', function(d) { return x(d.ordinal) - rectW / 2 + 0.5; })
.attr('y', -margin.top)
.attr('height', height + margin.top + margin.bottom)
.attr('width', rectW)
.on('mousemove', function(d) {
$tooltip.removeClass('uk-hidden').css({
left: x(d.ordinal) + margin.left + 10,
top: d3.event.layerY + 10
});
})
.on('mouseover', function(d) {
var hx = x(d.ordinal) + 0.5;
hover.attr('opacity', 1).attr('x1', hx).attr('x2', hx);
$.each(config, function(i, series) {
var value = d[series.name];
var text = series.format ? series.format(value) : value;
$tooltip.find('[data-point="' + series.name + '"]').text(text);
});
})
.on('mouseout', function(d) {
hover.attr('opacity', 0);
$tooltip.addClass('uk-hidden');
});
};
$(window).on('resize', function() {
if (+svg.attr('width') !== $container.width()) {
svg.selectAll('*').remove();
render();
}
});
render();
})(jQuery, d3);