Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / web_components / ui / chart_base.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.utils');
8 tvcm.require('telemetry.web_components.ui.d3');
9 tvcm.requireTemplate('telemetry.web_components.ui.chart_base');
10
11 tvcm.exportTo('telemetry.web_components.ui', function() {
12   var svgNS = 'http://www.w3.org/2000/svg';
13
14   function getColorOfKey(key) {
15     var id = tracing.getStringColorId(key);
16     return tracing.getColorPalette()[id];
17   }
18
19   /**
20    * A virtual base class for basic charts that provides X and Y axes, if
21    * needed, a title, and legend.
22    *
23    * @constructor
24    */
25   var ChartBase = tvcm.ui.define('svg', undefined, svgNS);
26
27   ChartBase.prototype = {
28     __proto__: HTMLUnknownElement.prototype,
29
30     decorate: function() {
31       this.classList.add('chart-base');
32       this.chartTitle_ = undefined;
33       this.data_ = undefined;
34       this.seriesKeys_ = undefined;
35       this.width_ = 400;
36       this.height_ = 300;
37
38       // This should use tvcm.instantiateTemplate. However, creating
39       // svg-namespaced elements inside a template isn't possible. Thus, this
40       // hack.
41       var template = document.head.querySelector('#chart-base-template');
42       var svgEl = template.content.querySelector('svg');
43       for (var i = 0; i < svgEl.children.length; i++)
44         this.appendChild(svgEl.children[i].cloneNode(true));
45     },
46
47     get chartTitle() {
48       return chartTitle_;
49     },
50
51     set chartTitle(chartTitle) {
52       this.chartTitle_ = chartTitle;
53       this.updateContents_();
54     },
55
56     get chartAreaElement() {
57       return this.querySelector('#chart-area');
58     },
59
60     get width() {
61       return width_;
62     },
63
64     set width(width) {
65       this.width_ = width;
66       this.updateContents_();
67     },
68
69     get height() {
70       return height_;
71     },
72
73     set height(height) {
74       this.height_ = height;
75       this.updateContents_();
76     },
77
78     get data() {
79       return this.data_;
80     },
81
82     get margin() {
83       var margin = {top: 20, right: 20, bottom: 30, left: 50};
84       if (this.chartTitle_)
85         margin.top += 20;
86       return margin;
87     },
88
89     get chartAreaSize() {
90       var margin = this.margin;
91       return {
92         width: this.width_ - margin.left - margin.right,
93         height: this.height_ - margin.top - margin.bottom
94       };
95     },
96
97     getLegendKeys_: function() {
98       throw new Error('Not implemented');
99     },
100
101     updateScales_: function(width, height) {
102       throw new Error('Not implemented');
103     },
104
105     updateContents_: function() {
106       var margin = this.margin;
107       var width = this.chartAreaSize.width;
108       var height = this.chartAreaSize.height;
109
110       var thisSel = d3.select(this);
111       thisSel.attr('width', this.width_);
112       thisSel.attr('height', this.height_);
113
114       var chartAreaSel = d3.select(this.chartAreaElement);
115       chartAreaSel.attr(
116           'transform',
117           'translate(' + margin.left + ',' + margin.top + ')');
118
119       this.updateScales_(width, height);
120
121       // Axes.
122       if (this.xScale_ && this.yScale_) {
123         var xAxisRenderer = d3.svg.axis()
124             .scale(this.xScale_)
125             .orient('bottom');
126
127         var yAxisRenderer = d3.svg.axis()
128             .scale(this.yScale_)
129             .orient('left');
130
131         chartAreaSel.select('.x.axis')
132             .attr('transform', 'translate(0,' + height + ')')
133             .call(xAxisRenderer);
134
135         chartAreaSel.select('.y.axis')
136             .call(yAxisRenderer);
137       }
138
139       // Title.
140       var titleSel = chartAreaSel.select('#title');
141       if (this.chartTitle_) {
142         titleSel.attr('transform', 'translate(' + width * 0.5 + ',-5)')
143             .style('display', undefined)
144             .style('text-anchor', 'middle')
145             .attr('class', 'title')
146             .attr('width', width)
147             .text(this.chartTitle_);
148       } else {
149         titleSel.style('display', 'none');
150       }
151
152       this.updateLegend_();
153     },
154
155     updateLegend_: function() {
156       var keys = this.getLegendKeys_();
157
158       var chartAreaSel = d3.select(this.chartAreaElement);
159       var chartAreaSize = this.chartAreaSize;
160
161       var legendEntriesSel = chartAreaSel.selectAll('.legend')
162           .data(keys.slice().reverse());
163
164       legendEntriesSel.enter()
165           .append('g')
166           .attr('class', 'legend')
167           .attr('transform', function(d, i) {
168             return 'translate(0,' + i * 20 + ')';
169           }).append('text').text(function(key) {
170             return key;
171           });
172       legendEntriesSel.exit().remove();
173
174       legendEntriesSel.attr('x', chartAreaSize.width - 18)
175           .attr('width', 18)
176           .attr('height', 18)
177           .style('fill', function(key) {
178             return getColorOfKey(key);
179           });
180
181       legendEntriesSel.selectAll('text')
182         .attr('x', chartAreaSize.width - 24)
183         .attr('y', 9)
184         .attr('dy', '.35em')
185         .style('text-anchor', 'end')
186         .text(function(d) { return d; });
187     }
188   };
189
190   return {
191     getColorOfKey: getColorOfKey,
192     ChartBase: ChartBase
193   };
194 });