11/*
2- A simple, lightweight jQuery plugin for creating sortable tables.
3- https://github.com/kylefox/jquery-tablesort
4- Version 0.0.1
2+ A simple, lightweight jQuery plugin for creating sortable tables.
3+ https://github.com/kylefox/jquery-tablesort
4+ Version 0.0.11
55*/
66
7- ; ( function ( $ ) {
8-
9- $ . tablesort = function ( $table , settings ) {
10- var self = this ;
11- this . $table = $table ;
12- this . settings = $ . extend ( { } , $ . tablesort . defaults , settings ) ;
13- this . $table . find ( 'thead th' ) . bind ( 'click.tablesort' , function ( ) {
14- if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
15- self . sort ( $ ( this ) ) ;
16- }
17- } ) ;
18- this . index = null ;
19- this . $th = null ;
20- this . direction = [ ] ;
21- } ;
22-
23- $ . tablesort . prototype = {
24-
25- sort : function ( th , direction ) {
26- var start = new Date ( ) ,
27- self = this ,
28- table = this . $table ,
29- rows = table . find ( 'tbody tr' ) ,
30- index = th . index ( ) ,
31- cache = [ ] ,
32- fragment = $ ( '<div/>' ) ,
33- sortValueForCell = function ( th , td , sorter ) {
34- var
35- sortBy
36- ;
37- if ( th . data ( ) . sortBy ) {
38- sortBy = th . data ( ) . sortBy ;
39- return ( typeof sortBy === 'function' )
40- ? sortBy ( th , td , sorter )
41- : sortBy
42- ;
43- }
44- return ( td . data ( 'sort' ) )
45- ? td . data ( 'sort' )
46- : td . text ( )
47- ;
48- } ,
49- naturalSort = function naturalSort ( a , b ) {
50- var
51- chunkRegExp = / ( ^ - ? [ 0 - 9 ] + ( \. ? [ 0 - 9 ] * ) [ d f ] ? e ? [ 0 - 9 ] ? $ | ^ 0 x [ 0 - 9 a - f ] + $ | [ 0 - 9 ] + ) / gi,
52- stripRegExp = / ( ^ [ ] * | [ ] * $ ) / g,
53- dateRegExp = / ( ^ ( [ \w ] + , ? [ \w ] + ) ? [ \w ] + , ? [ \w ] + \d + : \d + ( : \d + ) ? [ \w ] ? | ^ \d { 1 , 4 } [ \/ \- ] \d { 1 , 4 } [ \/ \- ] \d { 1 , 4 } | ^ \w + , \w + \d + , \d { 4 } ) / ,
54- numericRegExp = / ^ 0 x [ 0 - 9 a - f ] + $ / i,
55- oRegExp = / ^ 0 / ,
56- cLoc = 0 ,
57- useInsensitive = function ( string ) {
58- return ( '' + string ) . toLowerCase ( ) . replace ( ',' , '' ) ;
59- } ,
60- // convert all to strings strip whitespace
61- x = useInsensitive ( a ) . replace ( stripRegExp , '' ) || '' ,
62- y = useInsensitive ( b ) . replace ( stripRegExp , '' ) || '' ,
63- // chunk/tokenize
64- xChunked = x . replace ( chunkRegExp , '\0$1\0' ) . replace ( / \0 $ / , '' ) . replace ( / ^ \0 / , '' ) . split ( '\0' ) ,
65- yChunked = y . replace ( chunkRegExp , '\0$1\0' ) . replace ( / \0 $ / , '' ) . replace ( / ^ \0 / , '' ) . split ( '\0' ) ,
66- chunkLength = Math . max ( xChunked . length , yChunked . length ) ,
67- // numeric, hex or date detection
68- xDate = parseInt ( x . match ( numericRegExp ) , 10 ) || ( xChunked . length != 1 && x . match ( dateRegExp ) && Date . parse ( x ) ) ,
69- yDate = parseInt ( y . match ( numericRegExp ) , 10 ) || xDate && y . match ( dateRegExp ) && Date . parse ( y ) || null ,
70- xHexValue ,
71- yHexValue ,
72- index
73- ;
74- // first try and sort Hex codes or Dates
75- if ( yDate ) {
76- if ( xDate < yDate ) {
77- return - 1 ;
78- }
79- else if ( xDate > yDate ) {
80- return 1 ;
81- }
82- }
83- // natural sorting through split numeric strings and default strings
84- for ( index = 0 ; index < chunkLength ; index ++ ) {
85- // find floats not starting with '0', string or 0 if not defined (Clint Priest)
86- xHexValue = ! ( xChunked [ index ] || '' ) . match ( oRegExp ) && parseFloat ( xChunked [ index ] ) || xChunked [ index ] || 0 ;
87- yHexValue = ! ( yChunked [ index ] || '' ) . match ( oRegExp ) && parseFloat ( yChunked [ index ] ) || yChunked [ index ] || 0 ;
88- // handle numeric vs string comparison - number < string - (Kyle Adams)
89- if ( isNaN ( xHexValue ) !== isNaN ( yHexValue ) ) {
90- return ( isNaN ( xHexValue ) )
91- ? 1
92- : - 1
93- ;
94- }
95- // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
96- else if ( typeof xHexValue !== typeof yHexValue ) {
97- xHexValue += '' ;
98- yHexValue += '' ;
99- }
100- if ( xHexValue < yHexValue ) {
101- return - 1 ;
102- }
103- if ( xHexValue > yHexValue ) {
104- return 1 ;
105- }
106- }
107- return 0 ;
108- }
109- ;
110-
111- if ( rows . length === 0 ) {
112- return ;
113- }
114-
115- self . $table . find ( 'thead th' ) . removeClass ( self . settings . asc + ' ' + self . settings . desc ) ;
116-
117- this . $th = th ;
118- if ( this . index != index ) {
119- this . direction [ index ] = 'desc' ;
120- }
121- else if ( direction !== 'asc' && direction !== 'desc' ) {
122- this . direction [ index ] = this . direction [ index ] === 'desc' ? 'asc' : 'desc' ;
123- }
124- else {
125- this . direction [ index ] = direction ;
126- }
127- this . index = index ;
128- direction = this . direction [ index ] == 'asc' ? 1 : - 1 ;
129-
130- self . $table . trigger ( 'tablesort:start' , [ self ] ) ;
131- self . log ( "Sorting by " + this . index + ' ' + this . direction [ index ] ) ;
132-
133- rows . sort ( function ( a , b ) {
134- var aRow = $ ( a ) ;
135- var bRow = $ ( b ) ;
136- var aIndex = aRow . index ( ) ;
137- var bIndex = bRow . index ( ) ;
138-
139- // Sort value A
140- if ( cache [ aIndex ] ) {
141- a = cache [ aIndex ] ;
142- }
143- else {
144- a = sortValueForCell ( th , self . cellToSort ( a ) , self ) ;
145- cache [ aIndex ] = a ;
146- }
147- // Sort Value B
148- if ( cache [ bIndex ] ) {
149- b = cache [ bIndex ] ;
150- }
151- else {
152- b = sortValueForCell ( th , self . cellToSort ( b ) , self ) ;
153- cache [ bIndex ] = b ;
154- }
155- return ( naturalSort ( a , b ) * direction ) ;
156- } ) ;
157-
158- rows . each ( function ( i , tr ) {
159- fragment . append ( tr ) ;
160- } ) ;
161- table . append ( fragment . html ( ) ) ;
162-
163- th . addClass ( self . settings [ self . direction [ index ] ] ) ;
164-
165- self . log ( 'Sort finished in ' + ( ( new Date ( ) ) . getTime ( ) - start . getTime ( ) ) + 'ms' ) ;
166- self . $table . trigger ( 'tablesort:complete' , [ self ] ) ;
167-
168- } ,
169-
170- cellToSort : function ( row ) {
171- return $ ( $ ( row ) . find ( 'td' ) . get ( this . index ) ) ;
172- } ,
173-
174-
175- log : function ( msg ) {
176- if ( ( $ . tablesort . DEBUG || this . settings . debug ) && console && console . log ) {
177- console . log ( '[tablesort] ' + msg ) ;
178- }
179- } ,
180-
181- destroy : function ( ) {
182- this . $table . find ( 'thead th' ) . unbind ( 'click.tablesort' ) ;
183- this . $table . data ( 'tablesort' , null ) ;
184- return null ;
185- }
186-
187- } ;
188-
189- $ . tablesort . DEBUG = false ;
190-
191- $ . tablesort . defaults = {
192- debug : $ . tablesort . DEBUG ,
193- asc : 'sorted ascending' ,
194- desc : 'sorted descending'
195- } ;
196-
197- $ . fn . tablesort = function ( settings ) {
198- var table , sortable , previous ;
199- return this . each ( function ( ) {
200- table = $ ( this ) ;
201- previous = table . data ( 'tablesort' ) ;
202- if ( previous ) {
203- previous . destroy ( ) ;
204- }
205- table . data ( 'tablesort' , new $ . tablesort ( table , settings ) ) ;
206- } ) ;
207- } ;
208-
209- } ) ( jQuery ) ;
7+ ( function ( $ ) {
8+ $ . tablesort = function ( $table , settings ) {
9+ var self = this ;
10+ this . $table = $table ;
11+ this . $thead = this . $table . find ( 'thead' ) ;
12+ this . settings = $ . extend ( { } , $ . tablesort . defaults , settings ) ;
13+ this . $sortCells = this . $thead . length > 0 ? this . $thead . find ( 'th:not(.no-sort)' ) : this . $table . find ( 'th:not(.no-sort)' ) ;
14+ this . $sortCells . on ( 'click.tablesort' , function ( ) {
15+ self . sort ( $ ( this ) ) ;
16+ } ) ;
17+ this . index = null ;
18+ this . $th = null ;
19+ this . direction = null ;
20+ } ;
21+
22+ $ . tablesort . prototype = {
23+
24+ sort : function ( th , direction ) {
25+ var start = new Date ( ) ,
26+ self = this ,
27+ table = this . $table ,
28+ rowsContainer = table . find ( 'tbody' ) . length > 0 ? table . find ( 'tbody' ) : table ,
29+ rows = rowsContainer . find ( 'tr' ) . has ( 'td, th' ) ,
30+ cells = rows . find ( ':nth-child(' + ( th . index ( ) + 1 ) + ')' ) . filter ( 'td, th' ) ,
31+ sortBy = th . data ( ) . sortBy ,
32+ sortedMap = [ ] ;
33+
34+ var unsortedValues = cells . map ( function ( idx , cell ) {
35+ if ( sortBy )
36+ return ( typeof sortBy === 'function' ) ? sortBy ( $ ( th ) , $ ( cell ) , self ) : sortBy ;
37+ return ( $ ( this ) . data ( ) . sortValue != null ? $ ( this ) . data ( ) . sortValue : $ ( this ) . text ( ) ) ;
38+ } ) ;
39+ if ( unsortedValues . length === 0 ) return ;
40+
41+ //click on a different column
42+ if ( this . index !== th . index ( ) ) {
43+ this . direction = 'asc' ;
44+ this . index = th . index ( ) ;
45+ }
46+ else if ( direction !== 'asc' && direction !== 'desc' )
47+ this . direction = this . direction === 'asc' ? 'desc' : 'asc' ;
48+ else
49+ this . direction = direction ;
50+
51+ direction = this . direction == 'asc' ? 1 : - 1 ;
52+
53+ self . $table . trigger ( 'tablesort:start' , [ self ] ) ;
54+ self . log ( "Sorting by " + this . index + ' ' + this . direction ) ;
55+
56+ // Try to force a browser redraw
57+ self . $table . css ( "display" ) ;
58+ // Run sorting asynchronously on a timeout to force browser redraw after
59+ // `tablesort:start` callback. Also avoids locking up the browser too much.
60+ setTimeout ( function ( ) {
61+ self . $sortCells . removeClass ( self . settings . asc + ' ' + self . settings . desc ) ;
62+ for ( var i = 0 , length = unsortedValues . length ; i < length ; i ++ )
63+ {
64+ sortedMap . push ( {
65+ index : i ,
66+ cell : cells [ i ] ,
67+ row : rows [ i ] ,
68+ value : unsortedValues [ i ]
69+ } ) ;
70+ }
71+
72+ sortedMap . sort ( function ( a , b ) {
73+ return self . settings . compare ( a . value , b . value ) * direction ;
74+ } ) ;
75+
76+ $ . each ( sortedMap , function ( i , entry ) {
77+ rowsContainer . append ( entry . row ) ;
78+ } ) ;
79+
80+ th . addClass ( self . settings [ self . direction ] ) ;
81+
82+ self . log ( 'Sort finished in ' + ( ( new Date ( ) ) . getTime ( ) - start . getTime ( ) ) + 'ms' ) ;
83+ self . $table . trigger ( 'tablesort:complete' , [ self ] ) ;
84+ //Try to force a browser redraw
85+ self . $table . css ( "display" ) ;
86+ } , unsortedValues . length > 2000 ? 200 : 10 ) ;
87+ } ,
88+
89+ log : function ( msg ) {
90+ if ( ( $ . tablesort . DEBUG || this . settings . debug ) && console && console . log ) {
91+ console . log ( '[tablesort] ' + msg ) ;
92+ }
93+ } ,
94+
95+ destroy : function ( ) {
96+ this . $sortCells . off ( 'click.tablesort' ) ;
97+ this . $table . data ( 'tablesort' , null ) ;
98+ return null ;
99+ }
100+
101+ } ;
102+
103+ $ . tablesort . DEBUG = false ;
104+
105+ $ . tablesort . defaults = {
106+ debug : $ . tablesort . DEBUG ,
107+ asc : 'sorted ascending' ,
108+ desc : 'sorted descending' ,
109+ compare : function ( a , b ) {
110+ if ( a > b ) {
111+ return 1 ;
112+ } else if ( a < b ) {
113+ return - 1 ;
114+ } else {
115+ return 0 ;
116+ }
117+ }
118+ } ;
119+
120+ $ . fn . tablesort = function ( settings ) {
121+ var table , sortable , previous ;
122+ return this . each ( function ( ) {
123+ table = $ ( this ) ;
124+ previous = table . data ( 'tablesort' ) ;
125+ if ( previous ) {
126+ previous . destroy ( ) ;
127+ }
128+ table . data ( 'tablesort' , new $ . tablesort ( table , settings ) ) ;
129+ } ) ;
130+ } ;
131+
132+ } ) ( window . Zepto || window . jQuery ) ;
0 commit comments