diff options
Diffstat (limited to 'server/sonar-web/src/main/js/libs/graphics/barchart.js')
-rw-r--r-- | server/sonar-web/src/main/js/libs/graphics/barchart.js | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/libs/graphics/barchart.js b/server/sonar-web/src/main/js/libs/graphics/barchart.js new file mode 100644 index 00000000000..c107a68661b --- /dev/null +++ b/server/sonar-web/src/main/js/libs/graphics/barchart.js @@ -0,0 +1,142 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +(function ($) { + + function trans (left, top) { + return 'translate(' + left + ', ' + top + ')'; + } + + var defaults = function () { + return { + height: 140, + color: '#1f77b4', + interpolate: 'basis', + endDate: moment().format('YYYY-MM-DD'), + + marginLeft: 1, + marginRight: 1, + marginTop: 18, + marginBottom: 1 + }; + }; + + /* + * data = [ + * { val: '2015-01-30', count: 30 }, + * ... + * ] + */ + + $.fn.barchart = function (data) { + $(this).each(function () { + var options = _.defaults($(this).data(), defaults()); + _.extend(options, { + width: options.width || $(this).width(), + endDate: moment(options.endDate) + }); + + var container = d3.select(this), + svg = container.append('svg') + .attr('width', options.width + 2) + .attr('height', options.height + 2) + .classed('sonar-d3', true), + + plot = svg.append('g') + .classed('plot', true), + + xScale = d3.scale.ordinal() + .domain(data.map(function (d, i) { + return i; + })), + + yScaleMax = d3.max(data, function (d) { + return d.count; + }), + yScale = d3.scale.linear() + .domain([0, yScaleMax]); + + _.extend(options, { + availableWidth: options.width - options.marginLeft - options.marginRight, + availableHeight: options.height - options.marginTop - options.marginBottom + }); + + plot.attr('transform', trans(options.marginLeft, options.marginTop)); + xScale.rangeRoundBands([0, options.availableWidth], 0.05, 0); + yScale.range([3, options.availableHeight]); + + var barWidth = xScale.rangeBand(), + bars = plot.selectAll('g').data(data); + + if (barWidth > 0) { + var barsEnter = bars.enter() + .append('g') + .attr('transform', function (d, i) { + return trans(xScale(i), Math.ceil(options.availableHeight - yScale(d.count))); + }); + + barsEnter.append('rect') + .style('fill', options.color) + .attr('width', barWidth) + .attr('height', function (d) { + return Math.floor(yScale(d.count)); + }) + .style('cursor', 'pointer') + .attr('data-period-start', function (d) { + return moment(d.val).format('YYYY-MM-DD'); + }) + .attr('data-period-end', function (d, i) { + var beginning = moment(d.val), + ending = i < data.length - 1 ? moment(data[i + 1].val).subtract(1, 'days') : options.endDate, + isSameDay = ending.diff(beginning, 'days') <= 1; + if (isSameDay) { + ending.add(1, 'days'); + } + return ending.format('YYYY-MM-DD'); + }) + .attr('title', function (d, i) { + var beginning = moment(d.val), + ending = i < data.length - 1 ? moment(data[i + 1].val).subtract(1, 'days') : options.endDate, + isSameDay = ending.diff(beginning, 'days') <= 1; + return d.count + '<br>' + beginning.format('LL') + (isSameDay ? '' : (' – ' + ending.format('LL'))); + }) + .attr('data-placement', 'bottom') + .attr('data-toggle', 'tooltip'); + + var maxValue = d3.max(data, function (d) { + return d.count; + }), + isValueShown = false; + + barsEnter.append('text') + .classed('subtitle', true) + .attr('transform', trans(barWidth / 2, -4)) + .style('text-anchor', 'middle') + .text(function (d) { + var text = !isValueShown && d.count === maxValue ? d.count : ''; + isValueShown = d.count === maxValue; + return text; + }); + + $(this).find('[data-toggle=tooltip]').tooltip({ container: 'body', html: true }); + } + }); + }; + +})(window.jQuery); |