2 // new SortingTable( 'my_table', {
3 // zebra: true, // Stripe the table, also on initialize
4 // details: false, // Has details every other row
5 // paginator: false, // Pass a paginator object
6 // dont_sort_class: 'nosort', // Class name on th's that don't sort
7 // forward_sort_class: 'forward_sort', // Class applied to forward sort th's
8 // reverse_sort_class: 'reverse_sort' // Class applied to reverse sort th's
11 // The above were the defaults. The regexes in load_conversions test a cell
12 // begin sorted for a match, then use that conversion for all elements on that
15 // Requires mootools Class, Array, Function, Element, Element.Selectors,
16 // Element.Event, and you should probably get Window.DomReady if you're smart.
19 var SortingTable
= new Class({
27 dont_sort_class
: 'nosort',
28 forward_sort_class
: 'forward_sort',
29 reverse_sort_class
: 'reverse_sort'
32 initialize: function( table
, options
) {
33 this.table
= $(table
);
34 this.setOptions(options
);
37 this.tbody
= this.table
.getElement('tbody');
38 if (this.options
.zebra
) {
39 SortingTable
.stripe_table(this.tbody
.getChildren());
44 this.headers
= this.table
.getElement('thead').getElements('th');
45 this.headers
.each(function( header
, index
) {
46 if (header
.hasClass( this.options
.dont_sort_class
)) { return }
47 header
.store( 'column', index
+ skip
)
48 if (header
.colSpan
> 1) {
49 skip
= skip
+ header
.colSpan
- 1;
51 header
.addEvent( 'mousedown', function(evt
){
52 this.sort_by_header( evt
.target
);
53 if ( this.options
.paginator
) this.options
.paginator
.to_page( 1 );
57 this.load_conversions();
60 sort_by_header: function( header
){
63 var before
= this.tbody
.getPrevious();
66 var trs
= this.tbody
.getChildren();
67 while ( row
= trs
.shift() ) {
68 row
= { row
: row
.dispose() };
69 if ( this.options
.details
) {
70 row
.detail
= trs
.shift().dispose();
75 if ( this.sort_column
>= 0 &&
76 this.sort_column
== header
.retrieve('column') ) {
77 // They were pulled off in reverse
78 if ( header
.hasClass( this.options
.reverse_sort_class
) ) {
79 header
.removeClass( this.options
.reverse_sort_class
);
80 header
.addClass( this.options
.forward_sort_class
);
82 header
.removeClass( this.options
.forward_sort_class
);
83 header
.addClass( this.options
.reverse_sort_class
);
86 this.headers
.each(function(h
){
87 h
.removeClass( this.options
.forward_sort_class
);
88 h
.removeClass( this.options
.reverse_sort_class
);
90 this.sort_column
= header
.retrieve('column');
91 if (header
.retrieve('conversion_function')) {
92 this.conversion_matcher
= header
.retrieve('conversion_matcher');
93 this.conversion_function
= header
.retrieve('conversion_function');
95 this.conversion_function
= false;
96 rows
.some(function(row
){
97 var to_match
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
98 if (to_match
== '') return false;
99 this.conversions
.some(function(conversion
){
100 if (conversion
.matcher
.test( to_match
)){
101 this.conversion_matcher
= conversion
.matcher
;
102 this.conversion_function
= conversion
.conversion_function
;
107 return !!(this.conversion_function
);
109 header
.store('conversion_function', this.conversion_function
);
110 header
.store('conversion_matcher', this.conversion_matcher
);
112 header
.addClass( this.options
.forward_sort_class
);
113 rows
.each(function(row
){
114 var compare_value
= this.conversion_function( row
);
115 row
.toString = function(){
116 return compare_value
;
123 while ( row
= rows
.shift() ) {
124 this.tbody
.appendChild(row
.row
);
125 if (row
.detail
) this.tbody
.appendChild(row
.detail
);
126 if ( this.options
.zebra
) {
127 row
.row
.className
= row
.row
.className
.replace( this.removeAltClassRe
, '$1').clean();
129 row
.detail
.className
= row
.detail
.className
.replace( this.removeAltClassRe
, '$1').clean();
131 row
.row
.addClass( 'alt' );
132 if (row
.detail
) row
.detail
.addClass( 'alt' );
137 this.tbody
.inject(before
, 'after');
140 load_conversions: function() {
141 this.conversions
= $A([
142 // 1.75 MB, 301 GB, 34 KB, 8 TB
143 { matcher
: /([0-9.]{1,8}).*([KMGT]{1})B/,
144 conversion_function: function( row
) {
145 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
146 cell
= this.conversion_matcher
.exec( cell
);
147 if (!cell
) { return '0' }
148 if (cell
[2] == 'M') {
150 } else if (cell
[2] == 'G') {
152 } else if (cell
[2] == 'T') {
157 var i
= cell
[1].indexOf('.')
161 var dec
= cell
[1].split('.');
163 post
= dec
[1].concat('00'.substr(0,2-dec
[1].length
));
165 return sort_val
.concat('00000000'.substr(0,2-cell
[1].length
).concat(cell
[1])).concat(post
);
168 // 1 day ago, 4 days ago, 38 years ago, 1 month ago
169 { matcher
: /(\d{1,2}) (.{3,6}) ago/,
170 conversion_function: function( row
) {
171 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
172 cell
= this.conversion_matcher
.exec( cell
);
173 if (!cell
) { return '0' }
175 if (cell
[2].indexOf('month') != -1) {
177 } else if (cell
[2].indexOf('year') != -1) {
182 return sort_val
.concat('00'.substr(0,2-cell
[1].length
).concat(cell
[1]));
186 { matcher
: /((\d{1}\.\d{2}|\d{2}\.\d{2}|\d{3}\.\d{2}|\d{4}\.\d{2}|\d{5}\.\d{2}|\d{6}\.\d{2}))/,
187 conversion_function: function( row
) {
188 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
189 cell
= cell
.replace(/[^\d]/g, "");
190 return '00000000000000000000000000000000'.substr(0,32-cell
.length
).concat(cell
);
193 // YYYY-MM-DD, YYYY-m-d
194 { matcher
: /(\d{4})-(\d{1,2})-(\d{1,2})/,
195 conversion_function: function( row
) {
196 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
197 cell
= this.conversion_matcher
.exec( cell
);
200 '00'.substr(0,2-cell
[2].length
).concat(cell
[2])+
201 '00'.substr(0,2-cell
[3].length
).concat(cell
[3]);
203 return '00000000000000000000000000000000';
209 conversion_function: function( row
) {
210 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
211 return '00000000000000000000000000000000'.substr(0,32-cell
.length
).concat(cell
);
215 { matcher
: /^[0-9.,]+%$/,
216 conversion_function: function( row
) {
217 var cell
= $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
218 return '00000000000000000000000000000000'.substr(0,32-cell
.length
).concat(cell
);
223 conversion_function: function( row
) {
224 return $(row
.row
.getElementsByTagName('td')[this.sort_column
]).get('text');
232 SortingTable
.removeAltClassRe
= new RegExp('(^|\\s)alt(?:\\s|$)');
233 SortingTable
.implement({ removeAltClassRe
: SortingTable
.removeAltClassRe
});
235 SortingTable
.stripe_table = function ( tr_elements
) {
237 tr_elements
.each( function( tr
) {
238 if ( !tr
.hasClass('collapsed') ) counter
++;
239 tr
.className
= tr
.className
.replace( this.removeAltClassRe
, '$1').clean();
240 if (counter
% 2) tr
.addClass( 'alt' );
245 // AUTOLOAD CODE BLOCK
246 SortingTable
.scanPage = function() {
247 if ($("sorttable")) {
248 var tt
= new SortingTable("sorttable");
251 window
.addEvent("domready", SortingTable
.scanPage
);