Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / src / tvcm / ui / bar_chart.js
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.require('tvcm.range');
8 tvcm.require('tvcm.ui.d3');
9 tvcm.require('tvcm.ui.chart_base');
10
11 tvcm.requireStylesheet('tvcm.ui.bar_chart');
12
13 tvcm.exportTo('tvcm.ui', function() {
14   var ChartBase = tvcm.ui.ChartBase;
15   var getColorOfKey = tvcm.ui.getColorOfKey;
16
17   /**
18    * @constructor
19    */
20   var BarChart = tvcm.ui.define('bar-chart', ChartBase);
21
22   BarChart.prototype = {
23     __proto__: ChartBase.prototype,
24
25     decorate: function() {
26       ChartBase.prototype.decorate.call(this);
27       this.classList.add('bar-chart');
28
29       this.xScale_ = undefined;
30       this.xSubScale_ = undefined;
31       this.yScale_ = undefined;
32
33       this.data_ = undefined;
34       this.xLabelValues_ = undefined;
35       this.xLabelKey_ = undefined;
36       this.seriesKeys_ = undefined;
37     },
38
39     get data() {
40       return this.data_;
41     },
42
43     get xLabelKey() {
44       return this.xLabelKey_;
45     },
46
47     setDataAndXLabelKey: function(data, xLabelKey) {
48       if (data !== undefined) {
49         // Figure out what the series keys are. E.g. for {label: 'a', value1: 3,
50         // value2: 4} compute ['value1', 'value2'].
51         var seriesKeys = [];
52         d3.keys(data[0]).forEach(function(k) {
53           if (k == xLabelKey)
54             return;
55           seriesKeys.push(k);
56         });
57
58         // Figure out the x labels in the data set. E.g. from
59         //   [{label: 'a', ...}, {label: 'b', ...}]
60         // we would commpute ['a', 'y'].
61         var xLabelValues = [];
62         var seenXLabelValues = {};
63         data.forEach(function(d) {
64           var xLabelValue = d[xLabelKey];
65           if (seenXLabelValues[xLabelValue])
66             throw new Error('Label ' + xLabelValue + ' has been used already');
67           xLabelValues.push(xLabelValue);
68           seenXLabelValues[xLabelValue] = true;
69         }, this);
70         this.xLabelKey_ = xLabelKey;
71         this.seriesKeys_ = seriesKeys;
72         this.xLabelValues_ = xLabelValues;
73       } else {
74         this.xLabelKey_ = undefined;
75         this.seriesKeys_ = undefined;
76         this.xLabelValues_ = undefined;
77       }
78       this.data_ = data;
79       this.updateContents_();
80     },
81
82     getLegendKeys_: function() {
83       if (this.seriesKeys_ &&
84           this.seriesKeys_.length > 1)
85         return this.seriesKeys_.slice();
86       return [];
87     },
88
89     updateScales_: function(width, height) {
90       if (this.data_ === undefined) {
91         this.xScale_ = undefined;
92         this.xSubScale_ = undefined;
93         this.yScale_ = undefined;
94         return;
95       }
96
97       // xScale maps x labels to a position in the overall timeline.
98       this.xScale_ = d3.scale.ordinal();
99       this.xScale_.rangeRoundBands([0, width], .1);
100       this.xScale_.domain(this.xLabelValues_);
101
102       // xSubScale maps an individual series to a position within its group
103       // of related bars.
104       this.xSubScale_ = d3.scale.ordinal();
105       this.xSubScale_.domain(this.seriesKeys_)
106           .rangeRoundBands([0, this.xScale_.rangeBand()]);
107
108       // Regular mapping of values to the full chart height.
109       var yRange = new tvcm.Range();
110       this.data_.forEach(function(d) {
111         this.seriesKeys_.forEach(function(k) {
112           yRange.addValue(d[k]);
113         }, this);
114       }, this);
115       this.yScale_ = d3.scale.linear();
116       this.yScale_.range([height, 0]);
117
118       this.yScale_.domain([yRange.min, yRange.max]);
119     },
120
121     updateContents_: function() {
122       ChartBase.prototype.updateContents_.call(this);
123       if (!this.data_)
124         return;
125
126       var width = this.chartAreaSize.width;
127       var height = this.chartAreaSize.height;
128
129       var chartAreaSel = d3.select(this.chartAreaElement);
130
131       // An index-group has the rects from the same array index in the source
132       // data set.
133       var indexGroupSel = chartAreaSel.selectAll('.index-group')
134           .data(this.data_);
135       indexGroupSel.enter().append('g')
136           .attr('class', '.index-group')
137           .attr('transform', function(d) {
138             var k = d[this.xLabelKey_];
139             return 'translate(' + this.xScale_(k) + ',0)';
140           }.bind(this));
141       indexGroupSel.exit().remove();
142
143       // Within an index group, create a rect for each actual value.
144       var rectsSel = indexGroupSel.selectAll('rect')
145         .data(function(d) {
146             // 'd' is an index in the original array. We want to extract out the
147             // actual values from it from this.seriesKeys_. This we turn into
148             // {name: seriesKey, value: d[seriesKey]} objects that then get
149             // data-bound to each rect.
150             var values = [];
151             for (var i = 0; i < this.seriesKeys_.length; i++) {
152               var k = this.seriesKeys_[i];
153               values.push({name: k,
154                            value: d[k]});
155             }
156             return values;
157           }.bind(this));
158
159       rectsSel.enter().append('rect')
160         .attr('width', this.xSubScale_.rangeBand())
161         .attr('x', function(d) {
162             return this.xSubScale_(d.name);
163           }.bind(this))
164         .attr('y', function(d) {
165             return this.yScale_(d.value);
166           }.bind(this))
167         .attr('height', function(d) {
168             return height - this.yScale_(d.value);
169           }.bind(this))
170         .style('fill', function(d) {
171             return getColorOfKey(d.name);
172           });
173     }
174   };
175
176   return {
177     BarChart: BarChart
178   };
179 });