|
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
|
|