Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / src / tvcm / ui / sortable_table.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7 <link rel="import" href="/tvcm/ui.html">
8 <link rel="stylesheet" href="/tvcm/ui/sortable_table.css">
9 <script>
10 'use strict';
11
12 /**
13  * @fileoverview A sortable table with history states.
14  */
15 tvcm.exportTo('tvcm.ui', function() {
16   /**
17    * @constructor
18    */
19   var SortableTable = tvcm.ui.define('sortable-table');
20
21   var UNSORTED_ARROW = '&#x25BF';
22   var SORT_ASCENDING_ARROW = '&#x25BE';
23   var SORT_DESCENDING_ARROW = '&#x25B4';
24   var SORT_DIR_ASCENDING = 'downward';
25   var SORT_DIR_DESCENDING = 'upward';
26
27   SortableTable.prototype = {
28     __proto__: HTMLTableElement.prototype,
29
30     decorate: function() {
31       this.classList.add('sortable-table');
32       if (!this.tHead)
33         return;
34       var headerRow = this.tHead.rows[0];
35       var currentState = window.history.state;
36       for (var i = 0; i < headerRow.cells.length; i++) {
37         headerRow.cells[i].addEventListener('click',
38                                             this.onItemClicked_, true);
39         headerRow.cells[i].innerHTML += '&nbsp;' + UNSORTED_ARROW;
40       }
41
42       if (currentState && currentState.tableSorting) {
43         var hashCode = this.sortingHashCode_();
44         if (currentState.tableSorting[hashCode]) {
45           this.sort(currentState.tableSorting[hashCode].col,
46                     currentState.tableSorting[hashCode].sortDirection);
47         }
48       }
49     },
50
51     onItemClicked_: function(e) {
52       // 'this' refers to the table cell that has been clicked.
53       var headerRow = this.parentNode;
54       var table = headerRow.parentNode.parentNode;
55       var colIndex = Array.prototype.slice.call(headerRow.cells).indexOf(this);
56       var sortDirection = table.sort(colIndex);
57       var currentState = history.state;
58       if (!currentState.tableSorting)
59         currentState.tableSorting = {};
60       currentState.tableSorting[table.sortingHashCode_()] = {
61         col: colIndex,
62         sortDirection: sortDirection
63       };
64       window.history.pushState(currentState);
65     },
66
67     sort: function(colIndex, opt_sortDirection) {
68       var headerRow = this.tHead.rows[0];
69       var headerCell = headerRow.cells[colIndex];
70
71       if (!headerCell.hasAttribute('sort')) {
72         // we are either sorting a new column (not previously sorted),
73         // or sorting based on a given sort direction (opt_sortDirection).
74         return sortByColumn_(headerRow, headerCell, colIndex,
75                              opt_sortDirection);
76       } else {
77         // resort the current sort column in the other direction
78         return reverseSortDirection_(headerRow, headerCell, opt_sortDirection);
79       }
80       return sortDirection;
81     },
82
83     // A very simple hash function, based only on the header row and
84     // the table location. It is used to check that table loaded
85     // can be sorted according to the given history information.
86     sortingHashCode_: function() {
87       if (this.sortingHashValue_)
88         return this.sortingHashValue_;
89       var headerText = this.tHead.rows[0].innerText;
90       var hash = 0;
91       for (var i = 0; i < headerText.length; i++) {
92         if (headerText.charCodeAt(i) < 127)
93           hash += headerText.charCodeAt(i);
94       }
95
96       // use the table index as well in case the same table
97       // is displayed more than once on a single page.
98       var tableIndex = Array.prototype.slice.call(
99           document.getElementsByClassName('sortable-table')).indexOf(this);
100       this.sortingHashValue_ = tableIndex + '' + hash;
101       return this.sortingHashValue_;
102     }
103   };
104
105   function compareAscending_(a, b) {
106     return compare_(a, b);
107   }
108
109   function compareDescending_(a, b) {
110     return compare_(b, a);
111   }
112
113   function compare_(a, b) {
114     var a1 = parseFloat(a);
115     var b1 = parseFloat(b);
116     if (isNaN(a1) && isNaN(b1))
117       return a.toString().localeCompare(b.toString());
118     if (isNaN(a1))
119       return -1;
120     if (isNaN(b1))
121       return 1;
122     return a1 - b1;
123   }
124
125   function sortByColumn_(headerRow, headerCell, colIndex, opt_sortDirection) {
126     var sortDirection = opt_sortDirection || SORT_DIR_ASCENDING;
127     // remove sort attribute from other header elements.
128     for (var i = 0; i < headerRow.cells.length; i++) {
129       if (headerRow.cells[i].getAttribute('sort')) {
130         headerRow.cells[i].removeAttribute('sort');
131         var headerStr = headerRow.cells[i].innerHTML;
132         headerRow.cells[i].innerHTML =
133             headerStr.substr(0, headerStr.length - 2) + UNSORTED_ARROW;
134       }
135     }
136
137     var headerStr = headerRow.cells[colIndex].innerHTML;
138     headerCell.innerHTML = headerStr.substr(0, headerStr.length - 2) +
139                            (sortDirection == SORT_DIR_ASCENDING ?
140                             SORT_ASCENDING_ARROW : SORT_DESCENDING_ARROW);
141
142     headerCell.setAttribute('sort', sortDirection);
143     var rows = headerRow.parentNode.parentNode.tBodies[0].rows;
144     var tempRows = [];
145     for (var i = 0; i < rows.length; i++) {
146       tempRows.push([rows[i].cells[colIndex].innerText, rows[i]]);
147     }
148
149     tempRows.sort(sortDirection == SORT_DIR_ASCENDING ?
150                       compareAscending_ : compareDescending_);
151
152     for (var j = 0; j < tempRows.length; j++) {
153       headerRow.parentNode.parentNode.tBodies[0].
154           appendChild(tempRows[j][1]);
155     }
156     return sortDirection;
157   }
158
159   function reverseSortDirection_(headerRow, headerCell, opt_sortDirection) {
160     var sortDirection = headerCell.getAttribute('sort');
161     // if it is already sorted in the correct direction, do nothing.
162     if (opt_sortDirection == sortDirection)
163       return sortDirection;
164     sortDirection = sortDirection == SORT_DIR_DESCENDING ?
165                     SORT_DIR_ASCENDING : SORT_DIR_DESCENDING;
166     headerCell.setAttribute('sort', sortDirection);
167     var headerStr = headerCell.innerHTML;
168     headerCell.innerHTML = headerStr.substr(0, headerStr.length - 2) +
169                            (sortDirection == SORT_DIR_ASCENDING ?
170                             SORT_ASCENDING_ARROW : SORT_DESCENDING_ARROW);
171     // instead of re-sorting, we reverse the sorted rows.
172     var headerRow = headerCell.parentNode;
173     var tbody = headerRow.parentNode.parentNode.tBodies[0];
174     var tempRows = [];
175     for (var i = 0; i < tbody.rows.length; i++)
176       tempRows[tempRows.length] = tbody.rows[i];
177     for (var i = tempRows.length - 1; i >= 0; i--)
178       tbody.appendChild(tempRows[i]);
179     return sortDirection;
180   }
181
182   return {
183     SortableTable: SortableTable
184   };
185 });
186 </script>