Fossil SCM

fossil-scm / src / sorttable.js
Blame History Raw 173 lines
1
/* Javascript code that will enables sorting of the table. This code is
2
** derived from
3
**
4
** http://www.webtoolkit.info/sortable-html-table.html
5
**
6
** but with extensive modifications.
7
**
8
** All tables with class "sortable" are registered with the SortableTable()
9
** function. Example:
10
**
11
** <table class='sortable' data-column-types='tnkx' data-init-sort='2'>
12
**
13
** Column data types are determined by the data-column-types attribute of
14
** the table. The value of data-column-types is a string where each
15
** character of the string represents a datatype for one column in the
16
** table.
17
**
18
** t Sort by text
19
** n Sort numerically
20
** k Sort by the data-sortkey property
21
** x This column is not sortable
22
**
23
** Capital letters mean sort in reverse order.
24
** If there are fewer characters in zColumnTypes[] than their are columns,
25
** then all extra columns assume type "t" (text).
26
**
27
** If a column of the table is initially sorted, then the data-init-sort
28
** attribute should be set to the 1-based index of that column. (The
29
** left-most column is 1, the next column to the right is 2, and so forth.)
30
** A value of 0 in the data-init-sort attribute indicates that no columns
31
** where initially sorted.
32
**
33
** Clicking on the same column header twice in a row inverts the sort.
34
*/
35
function SortableTable(tableEl){
36
var columnTypes = tableEl.getAttribute("data-column-types");
37
var initSort = tableEl.getAttribute("data-init-sort");
38
this.tbody = tableEl.getElementsByTagName('tbody');
39
this.columnTypes = columnTypes;
40
if(tableEl.rows.length==0) return;
41
var ncols = tableEl.rows[0].cells.length;
42
for(var i = columnTypes.length; i<=ncols; i++){this.columnTypes += 't';}
43
this.sort = function (cell) {
44
var column = cell.cellIndex;
45
var sortFn;
46
switch( cell.sortType ){
47
case "n": sortFn = this.sortNumeric; break;
48
case "N": sortFn = this.sortReverseNumeric; break;
49
case "t": sortFn = this.sortText; break;
50
case "T": sortFn = this.sortReverseText; break;
51
case "k": sortFn = this.sortKey; break;
52
case "K": sortFn = this.sortReverseKey; break;
53
default: return;
54
}
55
this.sortIndex = column;
56
var newRows = new Array();
57
for (j = 0; j < this.tbody[0].rows.length; j++) {
58
newRows[j] = this.tbody[0].rows[j];
59
}
60
if( this.sortIndex==Math.abs(this.prevColumn)-1 ){
61
newRows.reverse();
62
this.prevColumn = -this.prevColumn;
63
}else{
64
newRows.sort(sortFn);
65
this.prevColumn = this.sortIndex+1;
66
}
67
for (i=0;i<newRows.length;i++) {
68
this.tbody[0].appendChild(newRows[i]);
69
}
70
this.setHdrIcons();
71
}
72
this.setHdrIcons = function() {
73
for (var i=0; i<this.hdrRow.cells.length; i++) {
74
if( this.columnTypes[i]=='x' ) continue;
75
var sortType;
76
if( this.prevColumn==i+1 ){
77
sortType = 'asc';
78
}else if( this.prevColumn==(-1-i) ){
79
sortType = 'desc'
80
}else{
81
sortType = 'none';
82
}
83
var hdrCell = this.hdrRow.cells[i];
84
var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, '');
85
clsName += ' sort ' + sortType;
86
hdrCell.className = clsName;
87
}
88
}
89
this.sortText = function(a,b) {
90
var i = thisObject.sortIndex;
91
if (a.cells.length<=i) return -1; /* see ticket 59d699710b1ab5d4 */
92
if (b.cells.length<=i) return 1;
93
aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
94
bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
95
if(aa<bb) return -1;
96
if(aa==bb) return a.rowIndex-b.rowIndex;
97
return 1;
98
}
99
this.sortReverseText = function(a,b) {
100
var i = thisObject.sortIndex;
101
if (a.cells.length<=i) return 1; /* see ticket 59d699710b1ab5d4 */
102
if (b.cells.length<=i) return -1;
103
aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
104
bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
105
if(aa<bb) return +1;
106
if(aa==bb) return a.rowIndex-b.rowIndex;
107
return -1;
108
}
109
this.sortNumeric = function(a,b) {
110
var i = thisObject.sortIndex;
111
aa = parseFloat(a.cells[i].textContent);
112
if (isNaN(aa)) aa = 0;
113
bb = parseFloat(b.cells[i].textContent);
114
if (isNaN(bb)) bb = 0;
115
if(aa==bb) return a.rowIndex-b.rowIndex;
116
return aa-bb;
117
}
118
this.sortReverseNumeric = function(a,b) {
119
var i = thisObject.sortIndex;
120
aa = parseFloat(a.cells[i].textContent);
121
if (isNaN(aa)) aa = 0;
122
bb = parseFloat(b.cells[i].textContent);
123
if (isNaN(bb)) bb = 0;
124
if(aa==bb) return a.rowIndex-b.rowIndex;
125
return bb-aa;
126
}
127
this.sortKey = function(a,b) {
128
var i = thisObject.sortIndex;
129
aa = a.cells[i].getAttribute("data-sortkey");
130
bb = b.cells[i].getAttribute("data-sortkey");
131
if(aa<bb) return -1;
132
if(aa==bb) return a.rowIndex-b.rowIndex;
133
return 1;
134
}
135
this.sortReverseKey = function(a,b) {
136
var i = thisObject.sortIndex;
137
aa = a.cells[i].getAttribute("data-sortkey");
138
bb = b.cells[i].getAttribute("data-sortkey");
139
if(aa<bb) return +1;
140
if(aa==bb) return a.rowIndex-b.rowIndex;
141
return -1;
142
}
143
var x = tableEl.getElementsByTagName('thead');
144
if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
145
return;
146
}
147
if(x && x[0].rows && x[0].rows.length > 0) {
148
this.hdrRow = x[0].rows[0];
149
} else {
150
return;
151
}
152
var thisObject = this;
153
this.prevColumn = initSort;
154
for (var i=0; i<this.hdrRow.cells.length; i++) {
155
if( columnTypes[i]=='x' ) continue;
156
var hdrcell = this.hdrRow.cells[i];
157
hdrcell.sTable = this;
158
hdrcell.style.cursor = "pointer";
159
hdrcell.sortType = columnTypes[i] || 't';
160
hdrcell.onclick = function () {
161
this.sTable.sort(this);
162
return false;
163
}
164
}
165
this.setHdrIcons()
166
}
167
(function(){
168
var x = document.getElementsByClassName("sortable");
169
for(var i=0; i<x.length; i++){
170
new SortableTable(x[i]);
171
}
172
}())
173

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button