- add sources.
[platform/framework/web/crosswalk.git] / src / tools / perf / utils / results_viewer / src / main.js
1 /**
2  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 'use strict';
7
8 (function() {
9   /**
10    * Main results viewer component.
11    */
12   var Viewer = ui.define('div');
13   (function() {
14     //"Private" functions for Viewer
15     /**
16      * Determines the appropriate parser for a given column, using it's first
17      * data element.
18      * @param {String} firstElement The first (non-header) element of a given
19      * column.
20      * @return {String} The YUI parser needed for the column.
21      */
22     function getColumnParser(firstElement) {
23       if (isNumeric(firstElement)) {
24         return 'number';
25       } else if (isDate(firstElement)) {
26         return 'date';
27       } else {
28         return 'string';
29       }
30     }
31
32     /**
33      * Determines whether or not the given element is a date.
34      * @param {String} str The string representation of a potential date.
35      * @return {boolean} true/false whether or not str can be parsed to
36      * a date.
37      */
38     function isDate(str) {
39       var timestamp = Date.parse(str);
40       return !isNaN(timestamp);
41     }
42
43     /**
44      * Generates the YUI column definition for the given dataset.
45      * @param {String[][]} dataSet the dataset that will be displayed.
46      * @return {JSON[]} The array containing the column definitions.
47      */
48     function createYUIColumnDefinitions(dataSet) {
49       var header = dataSet[0];
50       var firstRow = dataSet[1];
51       var columnDefinitions = [];
52       header.forEach(function (element, index, array) {
53         columnDefinitions.push({
54           'key' : index.toString(),
55           'label':element.toString(),
56           'maxAutoWidth':95,
57           'sortable':true,
58           'parser':getColumnParser(firstRow[index])});
59       });
60       return columnDefinitions;
61     }
62
63     /**
64      * Generates the YUI data source for the given dataset.
65      * @param {String[][]} dataSet the dataset that will be displayed.
66      * @return {YAHOO.util.FunctionDataSource} The YUI data source
67      * derived from the dataset.
68      */
69     function createYUIDataSource(dataSet) {
70       var dataSource = [];
71       //Starts from the first non-header line.
72       for (var i = 1; i < dataSet.length; i++) {
73         var dataSourceLine = {};
74         dataSet[i].forEach(function (element, index, array) {
75           if (isNumeric(element)) {
76             dataSourceLine[index.toString()] = parseFloat(element);
77           } else {
78             dataSourceLine[index.toString()] = element
79           }
80         });
81         dataSource.push(dataSourceLine);
82       }
83       return new YAHOO.util.FunctionDataSource(function() {
84                                                return dataSource});
85     }
86
87     /**
88      * Un-selects all the columns from the given data table.
89      * @param {YAHOO.widget.DataTable} dataTable The data table that
90      * contains the results.
91      */
92     function unselectAllColumns(dataTable) {
93       var selectedColumns = dataTable.getSelectedColumns();
94       for (var i = 0; i < selectedColumns.length; i++) {
95         dataTable.unselectColumn(selectedColumns[i]);
96       }
97     }
98
99     /**
100      * Generates an array that contains the indices of the selected
101      * columns in the data table.
102      * @param {YAHOO.widget.DataTable} dataTable
103      * @return {int[]} An array with the indices of the selected columns.
104      */
105     function getSelectedColumnIndices(dataTable) {
106       var selectedColumnIndices = [];
107       var selectedColumns = dataTable.getSelectedColumns();
108       for (var i = 0; i < selectedColumns.length; i++) {
109         selectedColumnIndices.push(selectedColumns[i].key);
110       }
111       return selectedColumnIndices;
112     }
113
114     Viewer.prototype = {
115       __proto__: HTMLDivElement.prototype,
116       decorate:function() {
117         /**
118          * The id for the element that contains the barchart (Optional).
119          * @type {String}
120          */
121         this.barChartElementId_ = undefined;
122         /**
123          * The rectangular array that contains the contents of the cvs file.
124          * @type {String[][]}
125          */
126         this.dataSet_ = undefined;
127       },
128       set barChartElementId(e) {
129         this.barChartElementId_ = e;
130       },
131       get barChartElementId() {
132         return this.barChartElementId_;
133       },
134       set dataSet(ds) {
135         this.dataSet_ = ds;
136       },
137       get dataSet() {
138         return this.dataSet_;
139       },
140       /**
141        * Renders the Viewer component.
142        * @expose
143        */
144       render: function() {
145         document.body.appendChild(this);
146         var previousBarChart = this.barChartElementId_ != null ?
147                                $(this.barChartElementId_) : null;
148         if (previousBarChart != null) {
149           document.body.removeChild(previousBarChart);
150           window.location.hash = this.id;
151         }
152
153         var columnDefinitions = createYUIColumnDefinitions(this.dataSet_);
154         var dataSource = createYUIDataSource(this.dataSet_);
155         var dataTable = new YAHOO.widget.DataTable(this.id, columnDefinitions,
156             dataSource, {caption:'Results'});
157         var firstRow = this.dataSet_[1];
158         var currentViewer = this;
159
160         dataTable.subscribe('cellClickEvent', function (oArgs) {
161           var selectedColumn = dataTable.getColumn(oArgs.target);
162           var selectedColumnIndex = parseInt(selectedColumn.key);
163
164           if (selectedColumnIndex == 0) {
165             unselectAllColumns(dataTable);
166             return;
167           }
168
169           if (isNumeric(firstRow[selectedColumnIndex])) {
170             dataTable.selectColumn(selectedColumn);
171             if (currentViewer.barChartElementId_ != null) {
172               var viewerBarChart_ =
173                       new ViewerBarChart({ownerDocument:window.document});
174               viewerBarChart_.id = currentViewer.barChartElementId_;
175               viewerBarChart_.dataSet = currentViewer.dataSet_;
176               viewerBarChart_.selectedColumnIndices
177                   = getSelectedColumnIndices(dataTable);
178               viewerBarChart_.render();
179             }
180           }
181         });
182       }
183     };
184   }());
185
186   /**
187    * BarChart component for the results viewer.
188    */
189   var ViewerBarChart = ui.define('div');
190   (function () {
191     //"Private" functions for ViewerBarChart
192     /**
193      * Generates a new array that contains only the first column, and all
194      * other selected columns.
195      * @param {(string|number)[][]} dataset Array with the csv contents.
196      * @param {int[]} selectedColumnIndices Indices for all the selected
197      * columns.
198      * @return {String[][]} A new array containing the first column
199      * and all selected columns.
200      */
201     function extractColumnsToPlot(dataset, selectedColumnIndices) {
202       var lines = [];
203       var line = [];
204       for (var i = 0; i < dataset.length; ++i) {
205         line.push(dataset[i][0]);
206         for (var j = 0; j < selectedColumnIndices.length; j++) {
207           var elementValue = dataset[i][selectedColumnIndices[j]];
208           line.push(isNumeric(elementValue) ? parseFloat(elementValue) :
209                         elementValue);
210         }
211         lines.push(line);
212         line = [];
213       }
214       return lines;
215     }
216
217     ViewerBarChart.prototype = {
218       __proto__:HTMLDivElement.prototype,
219       decorate: function() {
220         /**
221          * Percetage of the window width that will be used for the chart
222          * @const
223          * @type {float}
224          */
225         ViewerBarChart.PERCENTAGE_OF_WINDOW_WIDTH_FOR_CHART = 0.75;
226         /**
227          * Approximate number of pixels that will be used per line
228          * @const
229          * @type {int}
230          */
231         ViewerBarChart.HEIGHT_PER_LINE_IN_PIXELS = 28;
232
233         /**
234          * Raw dataset, which contains the csv file contents.
235          * @type {(String|number)[][]}
236          */
237         this.dataSet_ = undefined;
238         /**
239          * Array that contains the selected indices from the table view.
240          * @type {number[]}
241          */
242         this.selectedColumnIndices_ = undefined;
243       },
244       /**
245        * Renders the ViewerBarChart component.
246        * @expose
247        */
248       render : function() {
249         var existingBarChart = $(this.id);
250         if (existingBarChart != null) {
251           //Remove the previous bar chart
252           document.body.removeChild(existingBarChart);
253         }
254         //Attach this component to the document
255         document.body.appendChild(this);
256         var lines = extractColumnsToPlot(this.dataSet_,
257             this.selectedColumnIndices_);
258         var data = google.visualization.arrayToDataTable(lines);
259
260         var barCharWidth = window.width *
261                            ViewerBarChart.PERCENTAGE_OF_WINDOW_WIDTH_FOR_CHART;
262         var barCharHeight = this.dataSet_.length *
263                             ViewerBarChart.HEIGHT_PER_LINE_IN_PIXELS;
264         var options = {
265           'width': barCharWidth,
266           'height':barCharHeight,
267           'fontSize':15
268         };
269         new google.visualization.BarChart(this).draw(data, options);
270         window.location.hash = this.id;
271       },
272       set dataSet(ds) {
273         this.dataSet_ = ds;
274       },
275       set selectedColumnIndices(sci) {
276         this.selectedColumnIndices_ = sci;
277       }
278     };
279   }());
280
281   /**
282    * Determines whether or not a string can be parsed to a number.
283    * @param {String} element String representation of the potential number.
284    * @return {boolean} True or false depending on whether the element is
285    * numeric or not.
286    */
287   function isNumeric(element) {
288     return !isNaN(parseFloat(element)) && isFinite(element);
289   }
290
291   window.Viewer = Viewer;
292   window.ViewerBarChart = ViewerBarChart;
293 })();