aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/libs
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-05-29 14:28:20 +0200
committerStas Vilchik <vilchiks@gmail.com>2015-05-29 18:39:26 +0200
commitd3608358d7838429a4c0e068d82b37bec74e5d87 (patch)
tree92e173438071fd16744434c214a5104cede54f1f /server/sonar-web/src/main/js/libs
parentb542009c4736bdf93ab45e989117a6b7e7fef8f2 (diff)
downloadsonarqube-d3608358d7838429a4c0e068d82b37bec74e5d87.tar.gz
sonarqube-d3608358d7838429a4c0e068d82b37bec74e5d87.zip
move widgets from coffee to js
Diffstat (limited to 'server/sonar-web/src/main/js/libs')
-rw-r--r--server/sonar-web/src/main/js/libs/widgets/base.js93
-rw-r--r--server/sonar-web/src/main/js/libs/widgets/histogram.js164
-rw-r--r--server/sonar-web/src/main/js/libs/widgets/tag-cloud.js77
-rw-r--r--server/sonar-web/src/main/js/libs/widgets/treemap.js329
-rw-r--r--server/sonar-web/src/main/js/libs/widgets/word-cloud.js76
5 files changed, 739 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/libs/widgets/base.js b/server/sonar-web/src/main/js/libs/widgets/base.js
new file mode 100644
index 00000000000..3a788a0d615
--- /dev/null
+++ b/server/sonar-web/src/main/js/libs/widgets/base.js
@@ -0,0 +1,93 @@
+(function () {
+
+ if (window.SonarWidgets == null) {
+ window.SonarWidgets = {};
+ }
+
+ function BaseWidget () {
+ this.addField('components', []);
+ this.addField('metrics', []);
+ this.addField('metricsPriority', []);
+ this.addField('options', []);
+ }
+
+ BaseWidget.prototype.lineHeight = 20;
+ BaseWidget.prototype.colors4 = ['#ee0000', '#f77700', '#80cc00', '#00aa00'];
+ BaseWidget.prototype.colors4r = ['#00aa00', '#80cc00', '#f77700', '#ee0000'];
+ BaseWidget.prototype.colors5 = ['#ee0000', '#f77700', '#ffee00', '#80cc00', '#00aa00'];
+ BaseWidget.prototype.colors5r = ['#00aa00', '#80cc00', '#ffee00', '#f77700', '#ee0000'];
+ BaseWidget.prototype.colorsLevel = ['#d4333f', '#ff9900', '#85bb43', '##b4b4b4'];
+ BaseWidget.prototype.colorUnknown = '#777';
+
+
+ BaseWidget.prototype.addField = function (name, defaultValue) {
+ var privateName = '_' + name;
+ this[privateName] = defaultValue;
+ this[name] = function (d) {
+ return this.param.call(this, privateName, d);
+ };
+ return this;
+ };
+
+ BaseWidget.prototype.param = function (name, value) {
+ if (value == null) {
+ return this[name];
+ }
+ this[name] = value;
+ return this;
+ };
+
+ BaseWidget.prototype.addMetric = function (property, index) {
+ var key = this.metricsPriority()[index];
+ this[property] = _.extend(this.metrics()[key], {
+ key: key,
+ value: function (d) {
+ if (d.measures[key] != null) {
+ if (d.measures[key].text != null) {
+ return d.measures[key].text;
+ } else {
+ return d.measures[key].val;
+ }
+ }
+ },
+ formattedValue: function (d) {
+ if (d.measures[key] != null) {
+ if (d.measures[key].text != null) {
+ return d.measures[key].text;
+ } else {
+ return d.measures[key].fval;
+ }
+ }
+ }
+ });
+ return this;
+ };
+
+ BaseWidget.prototype.trans = function (left, top) {
+ return 'translate(' + left + ',' + top + ')';
+ };
+
+ BaseWidget.prototype.render = function (container) {
+ this.update(container);
+ return this;
+ };
+
+ BaseWidget.prototype.update = function () {
+ return this;
+ };
+
+ BaseWidget.prototype.tooltip = function (d) {
+ /* jshint nonbsp: false */
+ var title = d.longName;
+ if (this.colorMetric && (this.colorMetric.value(d) != null)) {
+ title += '\n' + this.colorMetric.name + ': ' + (this.colorMetric.formattedValue(d));
+ }
+ if (this.sizeMetric && (this.sizeMetric.value(d) != null)) {
+ title += '\n' + this.sizeMetric.name + ': ' + (this.sizeMetric.formattedValue(d));
+ }
+ return title;
+ };
+
+ window.SonarWidgets.BaseWidget = BaseWidget;
+
+})();
diff --git a/server/sonar-web/src/main/js/libs/widgets/histogram.js b/server/sonar-web/src/main/js/libs/widgets/histogram.js
new file mode 100644
index 00000000000..df902e893f6
--- /dev/null
+++ b/server/sonar-web/src/main/js/libs/widgets/histogram.js
@@ -0,0 +1,164 @@
+(function () {
+
+ function Histogram () {
+ window.SonarWidgets.BaseWidget.apply(this, arguments);
+ this.addField('width', 0);
+ this.addField('height', window.SonarWidgets.Histogram.defaults.height);
+ this.addField('margin', window.SonarWidgets.Histogram.defaults.margin);
+ this.addField('legendWidth', window.SonarWidgets.Histogram.defaults.legendWidth);
+ this.addField('maxResultsReached', false);
+ }
+
+ Histogram.prototype = new window.SonarWidgets.BaseWidget();
+
+ Histogram.prototype.barHeight = 16;
+
+ Histogram.prototype.barFill = '#1f77b4';
+
+ Histogram.prototype.isDataValid = function () {
+ var that = this;
+ return this.components().reduce(function (p, c) {
+ return p && !!c.measures[that.mainMetric.key];
+ }, true);
+ };
+
+ Histogram.prototype.truncate = function (text, type) {
+ var maxLength = 40;
+ switch (type) {
+ case 'FIL':
+ case 'CLA':
+ var n = text.length;
+ if (n > maxLength) {
+ var shortText = text.substr(n - maxLength + 2, n - 1),
+ dotIndex = shortText.indexOf('.');
+ return '...' + shortText.substr(dotIndex + 1);
+ } else {
+ return text;
+ }
+ break;
+ default:
+ if (text.length > maxLength) {
+ return text.substr(0, maxLength - 3) + '...';
+ } else {
+ return text;
+ }
+ }
+ };
+
+ Histogram.prototype.render = function (container) {
+ var box = d3.select(container);
+ this.addMetric('mainMetric', 0);
+ if (!this.isDataValid()) {
+ box.text(this.options().noMainMetric);
+ return;
+ }
+ this.width(box.property('offsetWidth'));
+ this.svg = box.append('svg').classed('sonar-d3', true);
+ this.gWrap = this.svg.append('g');
+ this.gWrap.attr('transform', this.trans(this.margin().left, this.margin().top));
+ this.plotWrap = this.gWrap.append('g').classed('plot', true);
+ this.x = d3.scale.linear();
+ this.y = d3.scale.ordinal();
+ this.metricLabel = this.gWrap.append('text').text(this.mainMetric.name);
+ this.metricLabel.attr('dy', '9px').style('font-size', '12px');
+ if (this.maxResultsReached()) {
+ this.maxResultsReachedLabel = this.gWrap.append('text').classed('max-results-reached-message', true);
+ this.maxResultsReachedLabel.text(this.options().maxItemsReachedMessage);
+ }
+ return window.SonarWidgets.BaseWidget.prototype.render.apply(this, arguments);
+ };
+
+ Histogram.prototype.update = function (container) {
+ var that = this;
+ var box = d3.select(container);
+ this.width(box.property('offsetWidth'));
+ var availableWidth = this.width() - this.margin().left - this.margin().right - this.legendWidth(),
+ availableHeight = this.barHeight * this.components().length + this.lineHeight,
+ totalHeight = availableHeight + this.margin().top + this.margin().bottom;
+ if (this.maxResultsReached()) {
+ totalHeight += this.lineHeight;
+ }
+ this.height(totalHeight);
+ this.svg.attr('width', this.width()).attr('height', this.height());
+ this.plotWrap.attr('transform', this.trans(0, this.lineHeight));
+ var xDomain = d3.extent(this.components(), function (d) {
+ return that.mainMetric.value(d);
+ });
+ if (!this.options().relativeScale) {
+ if (this.mainMetric.type === 'PERCENT') {
+ xDomain = [0, 100];
+ } else {
+ xDomain[0] = 0;
+ }
+ }
+ this.x.domain(xDomain).range([0, availableWidth]);
+ this.y.domain(this.components().map(function (d, i) {
+ return i;
+ })).rangeRoundBands([0, availableHeight], 0);
+ this.bars = this.plotWrap.selectAll('.bar').data(this.components());
+ this.barsEnter = this.bars.enter().append('g').classed('bar', true).attr('transform', function (d, i) {
+ return that.trans(0, i * that.barHeight);
+ });
+ this.barsEnter.append('rect').style('fill', this.barFill);
+ this.barsEnter.append('text')
+ .classed('legend-text component', true)
+ .style('text-anchor', 'end')
+ .attr('dy', '-0.35em')
+ .text(function (d) {
+ return that.truncate(d.longName, d.qualifier);
+ })
+ .attr('transform', function () {
+ return that.trans(that.legendWidth() - 10, that.barHeight);
+ });
+ this.barsEnter.append('text')
+ .classed('legend-text value', true)
+ .attr('dy', '-0.35em')
+ .text(function (d) {
+ return that.mainMetric.formattedValue(d);
+ })
+ .attr('transform', function (d) {
+ return that.trans(that.legendWidth() + that.x(that.mainMetric.value(d)) + 5, that.barHeight);
+ });
+ this.bars.selectAll('rect')
+ .transition()
+ .attr('x', this.legendWidth())
+ .attr('y', 0)
+ .attr('width', function (d) {
+ return Math.max(2, that.x(that.mainMetric.value(d)));
+ })
+ .attr('height', this.barHeight);
+ this.bars.selectAll('.component')
+ .transition()
+ .attr('transform', function () {
+ return that.trans(that.legendWidth() - 10, that.barHeight);
+ });
+ this.bars.selectAll('.value')
+ .transition()
+ .attr('transform', function (d) {
+ return that.trans(that.legendWidth() + that.x(that.mainMetric.value(d)) + 5, that.barHeight);
+ });
+ this.bars.exit().remove();
+ this.bars.on('click', function (d) {
+ window.location = that.options().baseUrl + '?id=' + encodeURIComponent(d.key);
+ });
+ this.metricLabel.attr('transform', this.trans(this.legendWidth(), 0));
+ if (this.maxResultsReached()) {
+ this.maxResultsReachedLabel.attr('transform',
+ this.trans(this.legendWidth(), this.height() - this.margin().bottom - 3));
+ }
+ return window.SonarWidgets.BaseWidget.prototype.update.apply(this, arguments);
+ };
+
+ window.SonarWidgets.Histogram = Histogram;
+ window.SonarWidgets.Histogram.defaults = {
+ height: 300,
+ margin: {
+ top: 4,
+ right: 50,
+ bottom: 4,
+ left: 10
+ },
+ legendWidth: 220
+ };
+
+})();
diff --git a/server/sonar-web/src/main/js/libs/widgets/tag-cloud.js b/server/sonar-web/src/main/js/libs/widgets/tag-cloud.js
new file mode 100644
index 00000000000..d09f38b55bb
--- /dev/null
+++ b/server/sonar-web/src/main/js/libs/widgets/tag-cloud.js
@@ -0,0 +1,77 @@
+(function () {
+
+ function TagCloud () {
+ window.SonarWidgets.BaseWidget.apply(this, arguments);
+ this.addField('width', []);
+ this.addField('height', []);
+ this.addField('tags', []);
+ this.addField('maxResultsReached', false);
+ }
+
+ TagCloud.prototype = new window.SonarWidgets.BaseWidget();
+
+ TagCloud.prototype.sizeHigh = 24;
+
+ TagCloud.prototype.sizeLow = 10;
+
+ TagCloud.prototype.renderWords = function () {
+ var that = this;
+ return window.requestMessages().done(function () {
+ var words = that.wordContainer.selectAll('.cloud-word').data(that.tags()),
+ wordsEnter = words.enter().append('a').classed('cloud-word', true);
+ wordsEnter.text(function (d) {
+ return d.key;
+ });
+ wordsEnter.attr('href', function (d) {
+ var url = that.options().baseUrl + '|tags=' + d.key;
+ if (that.options().createdAfter) {
+ url += '|createdAfter=' + that.options().createdAfter;
+ }
+ return url;
+ });
+ wordsEnter.attr('title', function (d) {
+ return that.tooltip(d);
+ });
+ words.style('font-size', function (d) {
+ return that.size(d.value) + 'px';
+ });
+ return words.sort(function (a, b) {
+ if (a.key.toLowerCase() > b.key.toLowerCase()) {
+ return 1;
+ } else {
+ return -1;
+ }
+ });
+ });
+ };
+
+ TagCloud.prototype.render = function (container) {
+ var box = d3.select(container).append('div');
+ box.classed('sonar-d3', true);
+ box.classed('cloud-widget', true);
+ this.wordContainer = box.append('div');
+ var sizeDomain = d3.extent(this.tags(), function (d) {
+ return d.value;
+ });
+ this.size = d3.scale.linear().domain(sizeDomain).range([this.sizeLow, this.sizeHigh]);
+ if (this.maxResultsReached()) {
+ var maxResultsReachedLabel = box.append('div').text(this.options().maxItemsReachedMessage);
+ maxResultsReachedLabel.classed('max-results-reached-message', true);
+ }
+ this.renderWords();
+ return window.SonarWidgets.BaseWidget.prototype.render.apply(this, arguments);
+ };
+
+ TagCloud.prototype.tooltip = function (d) {
+ var suffixKey = d.value === 1 ? 'issue' : 'issues',
+ suffix = t(suffixKey);
+ return (d.value + '\u00a0') + suffix;
+ };
+
+ TagCloud.prototype.parseSource = function (response) {
+ return this.tags(response.tags);
+ };
+
+ window.SonarWidgets.TagCloud = TagCloud;
+
+})();
diff --git a/server/sonar-web/src/main/js/libs/widgets/treemap.js b/server/sonar-web/src/main/js/libs/widgets/treemap.js
new file mode 100644
index 00000000000..f9cc1992833
--- /dev/null
+++ b/server/sonar-web/src/main/js/libs/widgets/treemap.js
@@ -0,0 +1,329 @@
+(function () {
+
+ function Treemap () {
+ this.addField('width', null);
+ this.addField('height', null);
+ this.addField('maxResultsReached', false);
+ window.SonarWidgets.BaseWidget.apply(this, arguments);
+ }
+
+ Treemap.prototype = new window.SonarWidgets.BaseWidget();
+
+ Treemap.prototype.sizeLow = 11;
+
+ Treemap.prototype.sizeHigh = 18;
+
+ Treemap.prototype.getNodes = function () {
+ return this.treemap
+ .nodes({ children: this.components() })
+ .filter(function (d) {
+ return !d.children;
+ });
+ };
+
+ Treemap.prototype.renderTreemap = function () {
+ var that = this;
+ var nodes = this.getNodes();
+ this.cells = this.box.selectAll('.treemap-cell').data(nodes);
+ this.cells.exit().remove();
+ var cellsEnter = this.cells.enter().append('div');
+ cellsEnter.classed('treemap-cell', true);
+ cellsEnter.append('div').classed('treemap-inner', true);
+ cellsEnter.append('a').classed('treemap-link', true);
+ this.cells.attr('title', function (d) {
+ return that.tooltip(d);
+ });
+ this.cells.style('background-color', function (d) {
+ if (that.colorMetric.value(d) != null) {
+ return that.color(that.colorMetric.value(d));
+ } else {
+ return that.colorUnknown;
+ }
+ });
+ this.cells.classed('treemap-cell-drilldown', function (d) {
+ return (d.qualifier != null) && d.qualifier !== 'FIL' && d.qualifier !== 'CLA';
+ });
+ var prefix = this.mostCommonPrefix(_.pluck(this.components(), 'longName')),
+ prefixLength = prefix.length;
+ this.cellsInner = this.box.selectAll('.treemap-inner').data(nodes);
+ this.cellsInner.html(function (d) {
+ if (prefixLength > 0) {
+ return prefix + '<br>' + (d.longName.substr(prefixLength));
+ } else {
+ return d.longName;
+ }
+ });
+ this.cellsLink = this.box.selectAll('.treemap-link').data(nodes);
+ this.cellsLink.html('<i class="icon-link"></i>');
+ this.cellsLink.attr('href', function (d) {
+ return that.options().baseUrl + '?id=' + encodeURIComponent(d.key);
+ });
+ this.attachEvents(cellsEnter);
+ return this.maxResultsReachedLabel.style('display', this.maxResultsReached() ? 'block' : 'none');
+ };
+
+ Treemap.prototype.updateTreemap = function (components, maxResultsReached) {
+ this.components(components);
+ this.maxResultsReached(maxResultsReached);
+ this.renderTreemap();
+ return this.positionCells();
+ };
+
+ Treemap.prototype.attachEvents = function (cells) {
+ var that = this;
+ return cells.on('click', function (d) {
+ return that.requestChildren(d);
+ });
+ };
+
+ Treemap.prototype.positionCells = function () {
+ var that = this;
+ this.cells.style('left', function (d) {
+ return d.x + 'px';
+ });
+ this.cells.style('top', function (d) {
+ return d.y + 'px';
+ });
+ this.cells.style('width', function (d) {
+ return d.dx + 'px';
+ });
+ this.cellsInner.style('max-width', function (d) {
+ return d.dx + 'px';
+ });
+ this.cells.style('height', function (d) {
+ return d.dy + 'px';
+ });
+ this.cells.style('line-height', function (d) {
+ return d.dy + 'px';
+ });
+ this.cells.style('font-size', function (d) {
+ return (that.size(d.dx / d.longName.length)) + 'px';
+ });
+ this.cellsLink.style('font-size', function (d) {
+ return (that.sizeLink(Math.min(d.dx, d.dy))) + 'px';
+ });
+ this.cells.classed('treemap-cell-small', function (d) {
+ return (d.dx / d.longName.length) < 1 || d.dy < 40;
+ });
+ return this.cells.classed('treemap-cell-very-small', function (d) {
+ return d.dx < 24 || d.dy < 24;
+ });
+ };
+
+ Treemap.prototype.renderLegend = function (box) {
+ this.legend = box.insert('div', ':first-child');
+ this.legend.classed('legend', true);
+ this.legend.classed('legend-html', true);
+ this.legend.append('span')
+ .classed('legend-text', true)
+ .html('Size: <span class="legend-text-main">' + this.sizeMetric.name + '</span>');
+ return this.legend.append('span')
+ .classed('legend-text', true)
+ .html('Color: <span class="legend-text-main">' + this.colorMetric.name + '</span>');
+ };
+
+ Treemap.prototype.renderBreadcrumbs = function (box) {
+ this.breadcrumbsBox = box.append('div').classed('treemap-breadcrumbs', true);
+ this.breadcrumbs = [];
+ var d = {
+ name: '<i class="icon-home"></i>',
+ components: this.components(),
+ maxResultsReached: this.maxResultsReached()
+ };
+ return this.addToBreadcrumbs(d);
+ };
+
+ Treemap.prototype.updateBreadcrumbs = function () {
+ var that = this;
+ var breadcrumbs = this.breadcrumbsBox.selectAll('.treemap-breadcrumbs-item').data(this.breadcrumbs);
+ breadcrumbs.exit().remove();
+ var breadcrumbsEnter = breadcrumbs.enter().append('span').classed('treemap-breadcrumbs-item', true);
+ breadcrumbsEnter.attr('title', function (d) {
+ if (d.longName != null) {
+ return d.longName;
+ } else {
+ return that.options().resource;
+ }
+ });
+ breadcrumbsEnter.append('i')
+ .classed('icon-chevron-right', true)
+ .style('display', function (d, i) {
+ if (i > 0) {
+ return 'inline';
+ } else {
+ return 'none';
+ }
+ });
+ breadcrumbsEnter.append('i').attr('class', function (d) {
+ if (d.qualifier != null) {
+ return 'icon-qualifier-' + (d.qualifier.toLowerCase());
+ } else {
+ return '';
+ }
+ });
+ var breadcrumbsEnterLinks = breadcrumbsEnter.append('a');
+ breadcrumbsEnterLinks.html(function (d) {
+ return d.name;
+ });
+ breadcrumbsEnterLinks.on('click', function (d) {
+ that.updateTreemap(d.components, d.maxResultsReached);
+ return that.cutBreadcrumbs(d);
+ });
+ this.breadcrumbsBox.style('display', this.breadcrumbs.length < 2 ? 'none' : 'block');
+ };
+
+ Treemap.prototype.addToBreadcrumbs = function (d) {
+ this.breadcrumbs.push(d);
+ this.updateBreadcrumbs();
+ };
+
+ Treemap.prototype.cutBreadcrumbs = function (lastElement) {
+ var index = null;
+ this.breadcrumbs.forEach(function (d, i) {
+ if (d.key === lastElement.key) {
+ index = i;
+ }
+ });
+ if (index != null) {
+ this.breadcrumbs = _.initial(this.breadcrumbs, this.breadcrumbs.length - index - 1);
+ this.updateBreadcrumbs();
+ }
+ };
+
+ Treemap.prototype.getColorScale = function () {
+ if (this.colorMetric.type === 'LEVEL') {
+ return this.getLevelColorScale();
+ }
+ if (this.colorMetric.type === 'RATING') {
+ return this.getRatingColorScale();
+ }
+ return this.getPercentColorScale();
+ };
+
+ Treemap.prototype.getPercentColorScale = function () {
+ var color = d3.scale.linear().domain([0, 25, 50, 75, 100]);
+ color.range(this.colorMetric.direction === 1 ? this.colors5 : this.colors5r);
+ return color;
+ };
+
+ Treemap.prototype.getRatingColorScale = function () {
+ var domain = [1, 2, 3, 4, 5];
+ if (this.components().length > 0) {
+ var colorMetricSample = this.colorMetric.value(_.first(this.components()));
+ if (typeof colorMetricSample === 'string') {
+ domain = ['A', 'B', 'C', 'D', 'E'];
+ }
+ }
+ return d3.scale.ordinal().domain(domain).range(this.colors5r);
+ };
+
+ Treemap.prototype.getLevelColorScale = function () {
+ return d3.scale.ordinal().domain(['ERROR', 'WARN', 'OK', 'NONE']).range(this.colorsLevel);
+ };
+
+ Treemap.prototype.render = function (container) {
+ var that = this;
+ var box = d3.select(container).append('div');
+ box.classed('sonar-d3', true);
+ this.box = box.append('div').classed('treemap-container', true);
+ this.addMetric('colorMetric', 0);
+ this.addMetric('sizeMetric', 1);
+ this.color = this.getColorScale();
+ this.size = d3.scale.linear().domain([3, 15]).range([this.sizeLow, this.sizeHigh]).clamp(true);
+ this.sizeLink = d3.scale.linear().domain([60, 100]).range([12, 14]).clamp(true);
+ this.treemap = d3.layout.treemap();
+ this.treemap.sort(function (a, b) {
+ return a.value - b.value;
+ });
+ this.treemap.round(true);
+ this.treemap.value(function (d) {
+ return that.sizeMetric.value(d);
+ });
+ this.maxResultsReachedLabel = box.append('div').text(this.options().maxItemsReachedMessage);
+ this.maxResultsReachedLabel.classed('max-results-reached-message', true);
+ this.renderLegend(box);
+ this.renderBreadcrumbs(box);
+ this.renderTreemap();
+ return window.SonarWidgets.BaseWidget.prototype.render.apply(this, arguments);
+ };
+
+ Treemap.prototype.update = function () {
+ this.width(this.box.property('offsetWidth'));
+ this.height(this.width() / 100.0 * this.options().heightInPercents);
+ this.box.style('height', (this.height()) + 'px');
+ this.treemap.size([this.width(), this.height()]);
+ this.cells.data(this.getNodes());
+ return this.positionCells();
+ };
+
+ Treemap.prototype.formatComponents = function (data) {
+ var that = this;
+ var components = _.filter(data, function (component) {
+ var hasSizeMetric = function () {
+ return _.findWhere(component.msr, {
+ key: that.sizeMetric.key
+ });
+ };
+ return _.isArray(component.msr) && component.msr.length > 0 && hasSizeMetric();
+ });
+ if (_.isArray(components) && components.length > 0) {
+ return components.map(function (component) {
+ var measures = {};
+ component.msr.forEach(function (measure) {
+ measures[measure.key] = {
+ val: measure.val,
+ fval: measure.frmt_val
+ };
+ });
+ return {
+ key: component.copy != null ? component.copy : component.key,
+ name: component.name,
+ longName: component.lname,
+ qualifier: component.qualifier,
+ measures: measures
+ };
+ });
+ }
+ };
+
+ Treemap.prototype.requestChildren = function (d) {
+ var that = this;
+ var metrics = this.metricsPriority().join(','),
+ RESOURCES_URL = baseUrl + '/api/resources/index';
+ return jQuery.get(RESOURCES_URL, {
+ resource: d.key,
+ depth: 1,
+ metrics: metrics
+ }).done(function (r) {
+ var components = that.formatComponents(r);
+ if (components != null) {
+ components = _.sortBy(components, function (d) {
+ return -that.sizeMetric.value(d);
+ });
+ components = _.initial(components, components.length - that.options().maxItems - 1);
+ that.updateTreemap(components, components.length > that.options().maxItems);
+ return that.addToBreadcrumbs(_.extend(d, {
+ components: components,
+ maxResultsReached: that.maxResultsReached()
+ }));
+ }
+ });
+ };
+
+ Treemap.prototype.mostCommonPrefix = function (strings) {
+ var sortedStrings = strings.slice(0).sort(),
+ firstString = sortedStrings[0],
+ firstStringLength = firstString.length,
+ lastString = sortedStrings[sortedStrings.length - 1],
+ i = 0;
+ while (i < firstStringLength && firstString.charAt(i) === lastString.charAt(i)) {
+ i++;
+ }
+ var prefix = firstString.substr(0, i),
+ lastPrefixPart = _.last(prefix.split(/[\s\\\/]/));
+ return prefix.substr(0, prefix.length - lastPrefixPart.length);
+ };
+
+ window.SonarWidgets.Treemap = Treemap;
+
+})();
diff --git a/server/sonar-web/src/main/js/libs/widgets/word-cloud.js b/server/sonar-web/src/main/js/libs/widgets/word-cloud.js
new file mode 100644
index 00000000000..c12e02390e4
--- /dev/null
+++ b/server/sonar-web/src/main/js/libs/widgets/word-cloud.js
@@ -0,0 +1,76 @@
+(function () {
+
+ function WordCloud () {
+ this.addField('width', []);
+ this.addField('height', []);
+ this.addField('maxResultsReached', false);
+ window.SonarWidgets.BaseWidget.apply(this, arguments);
+ }
+
+ WordCloud.prototype = new window.SonarWidgets.BaseWidget();
+
+ WordCloud.prototype.sizeHigh = 24;
+
+ WordCloud.prototype.sizeLow = 10;
+
+ WordCloud.prototype.renderWords = function () {
+ var that = this;
+ var words = this.wordContainer.selectAll('.cloud-word').data(this.components()),
+ wordsEnter = words.enter().append('a').classed('cloud-word', true);
+ wordsEnter.text(function (d) {
+ return d.name;
+ });
+ wordsEnter.attr('href', function (d) {
+ return that.options().baseUrl + '?id=' + encodeURIComponent(d.key);
+ });
+ wordsEnter.attr('title', function (d) {
+ return that.tooltip(d);
+ });
+ words.style('color', function (d) {
+ if (that.colorMetric.value(d) != null) {
+ return that.color(that.colorMetric.value(d));
+ } else {
+ return that.colorUnknown;
+ }
+ });
+ words.style('font-size', function (d) {
+ return (that.size(that.sizeMetric.value(d))) + 'px';
+ });
+ return words.sort(function (a, b) {
+ if (a.name.toLowerCase() > b.name.toLowerCase()) {
+ return 1;
+ } else {
+ return -1;
+ }
+ });
+ };
+
+ WordCloud.prototype.render = function (container) {
+ var that = this;
+ var box = d3.select(container).append('div');
+ box.classed('sonar-d3', true);
+ box.classed('cloud-widget', true);
+ this.wordContainer = box.append('div');
+ this.addMetric('colorMetric', 0);
+ this.addMetric('sizeMetric', 1);
+ this.color = d3.scale.linear().domain([0, 33, 67, 100]);
+ if (this.colorMetric.direction === 1) {
+ this.color.range(this.colors4);
+ } else {
+ this.color.range(this.colors4r);
+ }
+ var sizeDomain = d3.extent(this.components(), function (d) {
+ return that.sizeMetric.value(d);
+ });
+ this.size = d3.scale.linear().domain(sizeDomain).range([this.sizeLow, this.sizeHigh]);
+ if (this.maxResultsReached()) {
+ var maxResultsReachedLabel = box.append('div').text(this.options().maxItemsReachedMessage);
+ maxResultsReachedLabel.classed('max-results-reached-message', true);
+ }
+ this.renderWords();
+ return window.SonarWidgets.BaseWidget.prototype.render.apply(this, arguments);
+ };
+
+ window.SonarWidgets.WordCloud = WordCloud;
+
+})();