2007-10-17 19:53:27 +02:00
/ *
*
* Copyright ( c ) 2007 Andrew Tetlaw & Millstream Web Software
* http : //www.millstream.com.au/view/code/tablekit/
2008-08-21 17:30:51 +02:00
* Version : 1.3 b 2008 - 03 - 23
2009-06-08 21:24:28 +02:00
* Modified and improved by Inverse inc .
2008-08-21 17:30:51 +02:00
*
2007-10-17 19:53:27 +02:00
* Permission is hereby granted , free of charge , to any person
* obtaining a copy of this software and associated documentation
* files ( the "Software" ) , to deal in the Software without
* restriction , including without limitation the rights to use , copy ,
* modify , merge , publish , distribute , sublicense , and / or sell copies
* of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN
* ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
* *
* /
// Use the TableKit class constructure if you'd prefer to init your tables as JS objects
var TableKit = Class . create ( ) ;
TableKit . prototype = {
initialize : function ( elm , options ) {
var table = $ ( elm ) ;
if ( table . tagName !== "TABLE" ) {
return ;
}
TableKit . register ( table , Object . extend ( TableKit . options , options || { } ) ) ;
this . id = table . id ;
var op = TableKit . option ( 'sortable resizable editable' , this . id ) ;
if ( op . sortable ) {
TableKit . Sortable . init ( table ) ;
}
if ( op . resizable ) {
TableKit . Resizable . init ( table ) ;
}
if ( op . editable ) {
TableKit . Editable . init ( table ) ;
}
} ,
sort : function ( column , order ) {
TableKit . Sortable . sort ( this . id , column , order ) ;
} ,
resizeColumn : function ( column , w ) {
TableKit . Resizable . resize ( this . id , column , w ) ;
} ,
editCell : function ( row , column ) {
TableKit . Editable . editCell ( this . id , row , column ) ;
}
} ;
Object . extend ( TableKit , {
getBodyRows : function ( table ) {
table = $ ( table ) ;
var id = table . id ;
2008-08-21 17:30:51 +02:00
if ( ! TableKit . tables [ id ] . dom . rows ) {
TableKit . tables [ id ] . dom . rows = ( table . tHead && table . tHead . rows . length > 0 ) ? $A ( table . tBodies [ 0 ] . rows ) : $A ( table . rows ) . without ( table . rows [ 0 ] ) ;
2007-10-17 19:53:27 +02:00
}
2008-08-21 17:30:51 +02:00
return TableKit . tables [ id ] . dom . rows ;
2007-10-17 19:53:27 +02:00
} ,
getHeaderCells : function ( table , cell ) {
if ( ! table ) { table = $ ( cell ) . up ( 'table' ) ; }
var id = table . id ;
2008-08-21 17:30:51 +02:00
if ( ! TableKit . tables [ id ] . dom . head ) {
TableKit . tables [ id ] . dom . head = $A ( ( table . tHead && table . tHead . rows . length > 0 ) ? table . tHead . rows [ table . tHead . rows . length - 1 ] . cells : table . rows [ 0 ] . cells ) ;
2007-10-17 19:53:27 +02:00
}
2008-08-21 17:30:51 +02:00
return TableKit . tables [ id ] . dom . head ;
2007-10-17 19:53:27 +02:00
} ,
getCellIndex : function ( cell ) {
return $A ( cell . parentNode . cells ) . indexOf ( cell ) ;
} ,
getRowIndex : function ( row ) {
return $A ( row . parentNode . rows ) . indexOf ( row ) ;
} ,
getCellText : function ( cell , refresh ) {
if ( ! cell ) { return "" ; }
2008-08-21 17:30:51 +02:00
var data = TableKit . getCellData ( cell ) ;
2007-10-17 19:53:27 +02:00
if ( refresh || data . refresh || ! data . textContent ) {
data . textContent = cell . textContent ? cell . textContent : cell . innerText ;
data . refresh = false ;
}
return data . textContent ;
} ,
2008-08-21 17:30:51 +02:00
getCellData : function ( cell ) {
var t = null ;
if ( ! cell . id ) {
t = $ ( cell ) . up ( 'table' ) ;
cell . id = t . id + "-cell-" + TableKit . _getc ( ) ;
}
var tblid = t ? t . id : cell . id . match ( /(.*)-cell.*/ ) [ 1 ] ;
if ( ! TableKit . tables [ tblid ] . dom . cells [ cell . id ] ) {
TableKit . tables [ tblid ] . dom . cells [ cell . id ] = { textContent : '' , htmlContent : '' , active : false } ;
}
return TableKit . tables [ tblid ] . dom . cells [ cell . id ] ;
} ,
2007-10-17 19:53:27 +02:00
register : function ( table , options ) {
if ( ! table . id ) {
2008-08-21 17:30:51 +02:00
table . id = "tablekit-table-" + TableKit . _getc ( ) ;
2007-10-17 19:53:27 +02:00
}
var id = table . id ;
2008-08-21 17:30:51 +02:00
TableKit . tables [ id ] = TableKit . tables [ id ] ?
Object . extend ( TableKit . tables [ id ] , options || { } ) :
Object . extend (
{ dom : { head : null , rows : null , cells : { } } , sortable : false , resizable : false , editable : false } ,
options || { }
) ;
} ,
notify : function ( eventName , table , event ) {
if ( TableKit . tables [ table . id ] && TableKit . tables [ table . id ] . observers && TableKit . tables [ table . id ] . observers [ eventName ] ) {
TableKit . tables [ table . id ] . observers [ eventName ] ( table , event ) ;
2007-10-17 19:53:27 +02:00
}
2008-08-21 17:30:51 +02:00
TableKit . options . observers [ eventName ] ( table , event ) ( ) ;
2007-10-17 19:53:27 +02:00
} ,
isSortable : function ( table ) {
return TableKit . tables [ table . id ] ? TableKit . tables [ table . id ] . sortable : false ;
} ,
isResizable : function ( table ) {
return TableKit . tables [ table . id ] ? TableKit . tables [ table . id ] . resizable : false ;
} ,
isEditable : function ( table ) {
return TableKit . tables [ table . id ] ? TableKit . tables [ table . id ] . editable : false ;
} ,
setup : function ( o ) {
Object . extend ( TableKit . options , o || { } ) ;
} ,
option : function ( s , id , o1 , o2 ) {
o1 = o1 || TableKit . options ;
o2 = o2 || ( id ? ( TableKit . tables [ id ] ? TableKit . tables [ id ] : { } ) : { } ) ;
var key = id + s ;
if ( ! TableKit . _opcache [ key ] ) {
TableKit . _opcache [ key ] = $A ( $w ( s ) ) . inject ( [ ] , function ( a , v ) {
a . push ( a [ v ] = o2 [ v ] || o1 [ v ] ) ;
return a ;
} ) ;
}
return TableKit . _opcache [ key ] ;
} ,
e : function ( event ) {
return event || window . event ;
} ,
tables : { } ,
_opcache : { } ,
options : {
autoLoad : true ,
stripe : true ,
sortable : true ,
resizable : true ,
editable : true ,
rowEvenClass : 'roweven' ,
rowOddClass : 'rowodd' ,
sortableSelector : [ 'table.sortable' ] ,
columnClass : 'sortcol' ,
descendingClass : 'sortdesc' ,
ascendingClass : 'sortasc' ,
2008-08-21 17:30:51 +02:00
defaultSortDirection : 1 ,
2007-10-17 19:53:27 +02:00
noSortClass : 'nosort' ,
sortFirstAscendingClass : 'sortfirstasc' ,
sortFirstDecendingClass : 'sortfirstdesc' ,
resizableSelector : [ 'table.resizable' ] ,
minWidth : 10 ,
showHandle : true ,
resizeOnHandleClass : 'resize-handle-active' ,
editableSelector : [ 'table.editable' ] ,
formClassName : 'editable-cell-form' ,
noEditClass : 'noedit' ,
editAjaxURI : '/' ,
2008-08-21 17:30:51 +02:00
editAjaxOptions : { } ,
observers : {
'onSortStart' : function ( ) { } ,
'onSort' : function ( ) { } ,
'onSortEnd' : function ( ) { } ,
'onResizeStart' : function ( ) { } ,
'onResize' : function ( ) { } ,
'onResizeEnd' : function ( ) { } ,
'onEditStart' : function ( ) { } ,
'onEdit' : function ( ) { } ,
'onEditEnd' : function ( ) { }
}
} ,
_c : 0 ,
_getc : function ( ) { return TableKit . _c += 1 ; } ,
unloadTable : function ( table ) {
table = $ ( table ) ;
if ( ! TableKit . tables [ table . id ] ) { return ; } //if not an existing registered table return
var cells = TableKit . getHeaderCells ( table ) ;
var op = TableKit . option ( 'sortable resizable editable noSortClass descendingClass ascendingClass columnClass sortFirstAscendingClass sortFirstDecendingClass' , table . id ) ;
//unregister all the sorting and resizing events
cells . each ( function ( c ) {
c = $ ( c ) ;
if ( op . sortable ) {
if ( ! c . hasClassName ( op . noSortClass ) ) {
Event . stopObserving ( c , 'mousedown' , TableKit . Sortable . _sort ) ;
c . removeClassName ( op . columnClass ) ;
c . removeClassName ( op . sortFirstAscendingClass ) ;
c . removeClassName ( op . sortFirstDecendingClass ) ;
//ensure that if table reloaded current sort is remembered via sort first class name
if ( c . hasClassName ( op . ascendingClass ) ) {
c . removeClassName ( op . ascendingClass ) ;
c . addClassName ( op . sortFirstAscendingClass )
} else if ( c . hasClassName ( op . descendingClass ) ) {
c . removeClassName ( op . descendingClass ) ;
c . addClassName ( op . sortFirstDecendingClass )
}
}
}
if ( op . resizable ) {
Event . stopObserving ( c , 'mouseover' , TableKit . Resizable . initDetect ) ;
Event . stopObserving ( c , 'mouseout' , TableKit . Resizable . killDetect ) ;
}
} ) ;
//unregister the editing events and cancel any open editors
if ( op . editable ) {
Event . stopObserving ( table . tBodies [ 0 ] , 'click' , TableKit . Editable . _editCell ) ;
for ( var c in TableKit . tables [ table . id ] . dom . cells ) {
if ( TableKit . tables [ table . id ] . dom . cells [ c ] . active ) {
var cell = $ ( c ) ;
var editor = TableKit . Editable . getCellEditor ( cell ) ;
editor . cancel ( cell ) ;
}
}
}
//delete the cache
TableKit . tables [ table . id ] . dom = { head : null , rows : null , cells : { } } ; // TODO: watch this for mem leaks
} ,
reloadTable : function ( table ) {
table = $ ( table ) ;
TableKit . unloadTable ( table ) ;
var op = TableKit . option ( 'sortable resizable editable' , table . id ) ;
if ( op . sortable ) { TableKit . Sortable . init ( table ) ; }
if ( op . resizable ) { TableKit . Resizable . init ( table ) ; }
if ( op . editable ) { TableKit . Editable . init ( table ) ; }
} ,
reload : function ( ) {
for ( var k in TableKit . tables ) {
TableKit . reloadTable ( k ) ;
}
2007-10-17 19:53:27 +02:00
} ,
load : function ( ) {
if ( TableKit . options . autoLoad ) {
if ( TableKit . options . sortable ) {
$A ( TableKit . options . sortableSelector ) . each ( function ( s ) {
$$ ( s ) . each ( function ( t ) {
TableKit . Sortable . init ( t ) ;
} ) ;
} ) ;
}
if ( TableKit . options . resizable ) {
$A ( TableKit . options . resizableSelector ) . each ( function ( s ) {
$$ ( s ) . each ( function ( t ) {
TableKit . Resizable . init ( t ) ;
} ) ;
} ) ;
}
if ( TableKit . options . editable ) {
$A ( TableKit . options . editableSelector ) . each ( function ( s ) {
$$ ( s ) . each ( function ( t ) {
TableKit . Editable . init ( t ) ;
} ) ;
} ) ;
}
}
}
} ) ;
TableKit . Rows = {
stripe : function ( table ) {
var rows = TableKit . getBodyRows ( table ) ;
rows . each ( function ( r , i ) {
TableKit . Rows . addStripeClass ( table , r , i ) ;
} ) ;
} ,
addStripeClass : function ( t , r , i ) {
t = t || r . up ( 'table' ) ;
var op = TableKit . option ( 'rowEvenClass rowOddClass' , t . id ) ;
var css = ( ( i + 1 ) % 2 === 0 ? op [ 0 ] : op [ 1 ] ) ;
// using prototype's assClassName/RemoveClassName was not efficient for large tables, hence:
var cn = r . className . split ( /\s+/ ) ;
var newCn = [ ] ;
for ( var x = 0 , l = cn . length ; x < l ; x += 1 ) {
if ( cn [ x ] !== op [ 0 ] && cn [ x ] !== op [ 1 ] ) { newCn . push ( cn [ x ] ) ; }
}
newCn . push ( css ) ;
r . className = newCn . join ( " " ) ;
}
} ;
TableKit . Sortable = {
init : function ( elm , options ) {
var table = $ ( elm ) ;
if ( table . tagName !== "TABLE" ) {
return ;
}
TableKit . register ( table , Object . extend ( options || { } , { sortable : true } ) ) ;
var sortFirst ;
var cells = TableKit . getHeaderCells ( table ) ;
var op = TableKit . option ( 'noSortClass columnClass sortFirstAscendingClass sortFirstDecendingClass' , table . id ) ;
cells . each ( function ( c ) {
c = $ ( c ) ;
if ( ! c . hasClassName ( op . noSortClass ) ) {
Event . observe ( c , 'mousedown' , TableKit . Sortable . _sort ) ;
c . addClassName ( op . columnClass ) ;
if ( c . hasClassName ( op . sortFirstAscendingClass ) || c . hasClassName ( op . sortFirstDecendingClass ) ) {
sortFirst = c ;
}
}
} ) ;
if ( sortFirst ) {
if ( sortFirst . hasClassName ( op . sortFirstAscendingClass ) ) {
TableKit . Sortable . sort ( table , sortFirst , 1 ) ;
} else {
TableKit . Sortable . sort ( table , sortFirst , - 1 ) ;
}
} else { // just add row stripe classes
TableKit . Rows . stripe ( table ) ;
}
} ,
reload : function ( table ) {
table = $ ( table ) ;
var cells = TableKit . getHeaderCells ( table ) ;
var op = TableKit . option ( 'noSortClass columnClass' , table . id ) ;
cells . each ( function ( c ) {
c = $ ( c ) ;
if ( ! c . hasClassName ( op . noSortClass ) ) {
Event . stopObserving ( c , 'mousedown' , TableKit . Sortable . _sort ) ;
c . removeClassName ( op . columnClass ) ;
}
} ) ;
TableKit . Sortable . init ( table ) ;
} ,
_sort : function ( e ) {
if ( TableKit . Resizable . _onHandle ) { return ; }
e = TableKit . e ( e ) ;
Event . stop ( e ) ;
2009-06-08 21:24:28 +02:00
var cell = e . element ( ) ;
2007-10-17 19:53:27 +02:00
while ( ! ( cell . tagName && cell . tagName . match ( /td|th/gi ) ) ) {
cell = cell . parentNode ;
}
TableKit . Sortable . sort ( null , cell ) ;
} ,
sort : function ( table , index , order ) {
var cell ;
if ( typeof index === 'number' ) {
if ( ! table || ( table . tagName && table . tagName !== "TABLE" ) ) {
return ;
}
table = $ ( table ) ;
index = Math . min ( table . rows [ 0 ] . cells . length , index ) ;
index = Math . max ( 1 , index ) ;
index -= 1 ;
cell = ( table . tHead && table . tHead . rows . length > 0 ) ? $ ( table . tHead . rows [ table . tHead . rows . length - 1 ] . cells [ index ] ) : $ ( table . rows [ 0 ] . cells [ index ] ) ;
} else {
cell = $ ( index ) ;
table = table ? $ ( table ) : cell . up ( 'table' ) ;
index = TableKit . getCellIndex ( cell ) ;
}
2008-08-21 17:30:51 +02:00
var op = TableKit . option ( 'noSortClass descendingClass ascendingClass defaultSortDirection' , table . id ) ;
2007-10-17 19:53:27 +02:00
if ( cell . hasClassName ( op . noSortClass ) ) { return ; }
2008-08-21 17:30:51 +02:00
//TableKit.notify('onSortStart', table);
order = order ? order : op . defaultSortDirection ;
2007-10-17 19:53:27 +02:00
var rows = TableKit . getBodyRows ( table ) ;
if ( cell . hasClassName ( op . ascendingClass ) || cell . hasClassName ( op . descendingClass ) ) {
rows . reverse ( ) ; // if it was already sorted we just need to reverse it.
2008-08-21 17:30:51 +02:00
order = cell . hasClassName ( op . descendingClass ) ? 1 : - 1 ;
2007-10-17 19:53:27 +02:00
} else {
var datatype = TableKit . Sortable . getDataType ( cell , index , table ) ;
var tkst = TableKit . Sortable . types ;
rows . sort ( function ( a , b ) {
return order * tkst [ datatype ] . compare ( TableKit . getCellText ( a . cells [ index ] ) , TableKit . getCellText ( b . cells [ index ] ) ) ;
} ) ;
}
var tb = table . tBodies [ 0 ] ;
var tkr = TableKit . Rows ;
rows . each ( function ( r , i ) {
tb . appendChild ( r ) ;
tkr . addStripeClass ( table , r , i ) ;
} ) ;
var hcells = TableKit . getHeaderCells ( null , cell ) ;
$A ( hcells ) . each ( function ( c , i ) {
c = $ ( c ) ;
c . removeClassName ( op . ascendingClass ) ;
c . removeClassName ( op . descendingClass ) ;
if ( index === i ) {
if ( order === 1 ) {
c . addClassName ( op . ascendingClass ) ;
} else {
c . addClassName ( op . descendingClass ) ;
}
}
} ) ;
} ,
types : { } ,
detectors : [ ] ,
addSortType : function ( ) {
$A ( arguments ) . each ( function ( o ) {
TableKit . Sortable . types [ o . name ] = o ;
} ) ;
} ,
getDataType : function ( cell , index , table ) {
cell = $ ( cell ) ;
index = ( index || index === 0 ) ? index : TableKit . getCellIndex ( cell ) ;
var colcache = TableKit . Sortable . _coltypecache ;
var cache = colcache [ table . id ] ? colcache [ table . id ] : ( colcache [ table . id ] = { } ) ;
if ( ! cache [ index ] ) {
2008-08-21 17:30:51 +02:00
var t = false ;
2007-10-17 19:53:27 +02:00
// first look for a data type id on the heading row cell
if ( cell . id && TableKit . Sortable . types [ cell . id ] ) {
2008-08-21 17:30:51 +02:00
t = cell . id
}
if ( ! t ) {
t = $w ( cell . className ) . detect ( function ( n ) { // then look for a data type classname on the heading row cell
return ( TableKit . Sortable . types [ n ] ) ? true : false ;
} ) ;
2007-10-17 19:53:27 +02:00
}
if ( ! t ) {
var rows = TableKit . getBodyRows ( table ) ;
cell = rows [ 0 ] . cells [ index ] ; // grab same index cell from body row to try and match data type
t = TableKit . Sortable . detectors . detect (
function ( d ) {
return TableKit . Sortable . types [ d ] . detect ( TableKit . getCellText ( cell ) ) ;
} ) ;
}
cache [ index ] = t ;
}
return cache [ index ] ;
} ,
_coltypecache : { }
} ;
TableKit . Sortable . detectors = $A ( $w ( 'date-iso date date-eu date-au time currency datasize number casesensitivetext text' ) ) ; // setting it here because Safari complained when I did it above...
TableKit . Sortable . Type = Class . create ( ) ;
TableKit . Sortable . Type . prototype = {
initialize : function ( name , options ) {
this . name = name ;
options = Object . extend ( {
normal : function ( v ) {
return v ;
} ,
pattern : /.*/
} , options || { } ) ;
this . normal = options . normal ;
this . pattern = options . pattern ;
if ( options . compare ) {
this . compare = options . compare ;
}
if ( options . detect ) {
this . detect = options . detect ;
}
} ,
compare : function ( a , b ) {
return TableKit . Sortable . Type . compare ( this . normal ( a ) , this . normal ( b ) ) ;
} ,
detect : function ( v ) {
return this . pattern . test ( v ) ;
}
} ;
TableKit . Sortable . Type . compare = function ( a , b ) {
return a < b ? - 1 : a === b ? 0 : 1 ;
} ;
TableKit . Sortable . addSortType (
new TableKit . Sortable . Type ( 'number' , {
pattern : /^[-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?/ ,
normal : function ( v ) {
// This will grab the first thing that looks like a number from a string, so you can use it to order a column of various srings containing numbers.
v = parseFloat ( v . replace ( /^.*?([-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?).*$/ , "$1" ) ) ;
return isNaN ( v ) ? 0 : v ;
} } ) ,
new TableKit . Sortable . Type ( 'text' , {
normal : function ( v ) {
return v ? v . toLowerCase ( ) : '' ;
} } ) ,
new TableKit . Sortable . Type ( 'casesensitivetext' , { pattern : /^[A-Z]+$/ } ) ,
new TableKit . Sortable . Type ( 'datasize' , {
pattern : /^[-+]?[\d]*\.?[\d]+(?:[eE][-+]?[\d]+)?\s?[k|m|g|t]b$/i ,
normal : function ( v ) {
var r = v . match ( /^([-+]?[\d]*\.?[\d]+([eE][-+]?[\d]+)?)\s?([k|m|g|t]?b)?/i ) ;
var b = r [ 1 ] ? Number ( r [ 1 ] ) . valueOf ( ) : 0 ;
var m = r [ 3 ] ? r [ 3 ] . substr ( 0 , 1 ) . toLowerCase ( ) : '' ;
var result = b ;
switch ( m ) {
case 'k' :
result = b * 1024 ;
break ;
case 'm' :
result = b * 1024 * 1024 ;
break ;
case 'g' :
result = b * 1024 * 1024 * 1024 ;
break ;
case 't' :
result = b * 1024 * 1024 * 1024 * 1024 ;
break ;
}
return result ;
} } ) ,
new TableKit . Sortable . Type ( 'date-au' , {
pattern : /^\d{2}\/\d{2}\/\d{4}\s?(?:\d{1,2}\:\d{2}(?:\:\d{2})?\s?[a|p]?m?)?/i ,
normal : function ( v ) {
if ( ! this . pattern . test ( v ) ) { return 0 ; }
var r = v . match ( /^(\d{2})\/(\d{2})\/(\d{4})\s?(?:(\d{1,2})\:(\d{2})(?:\:(\d{2}))?\s?([a|p]?m?))?/i ) ;
var yr _num = r [ 3 ] ;
var mo _num = parseInt ( r [ 2 ] , 10 ) - 1 ;
var day _num = r [ 1 ] ;
var hr _num = r [ 4 ] ? r [ 4 ] : 0 ;
2008-08-21 17:30:51 +02:00
if ( r [ 7 ] ) {
var chr = parseInt ( r [ 4 ] , 10 ) ;
if ( r [ 7 ] . toLowerCase ( ) . indexOf ( 'p' ) !== - 1 ) {
hr _num = chr < 12 ? chr + 12 : chr ;
} else if ( r [ 7 ] . toLowerCase ( ) . indexOf ( 'a' ) !== - 1 ) {
hr _num = chr < 12 ? chr : 0 ;
}
}
2007-10-17 19:53:27 +02:00
var min _num = r [ 5 ] ? r [ 5 ] : 0 ;
var sec _num = r [ 6 ] ? r [ 6 ] : 0 ;
return new Date ( yr _num , mo _num , day _num , hr _num , min _num , sec _num , 0 ) . valueOf ( ) ;
} } ) ,
new TableKit . Sortable . Type ( 'date-us' , {
pattern : /^\d{2}\/\d{2}\/\d{4}\s?(?:\d{1,2}\:\d{2}(?:\:\d{2})?\s?[a|p]?m?)?/i ,
normal : function ( v ) {
if ( ! this . pattern . test ( v ) ) { return 0 ; }
var r = v . match ( /^(\d{2})\/(\d{2})\/(\d{4})\s?(?:(\d{1,2})\:(\d{2})(?:\:(\d{2}))?\s?([a|p]?m?))?/i ) ;
var yr _num = r [ 3 ] ;
var mo _num = parseInt ( r [ 1 ] , 10 ) - 1 ;
var day _num = r [ 2 ] ;
var hr _num = r [ 4 ] ? r [ 4 ] : 0 ;
2008-08-21 17:30:51 +02:00
if ( r [ 7 ] ) {
var chr = parseInt ( r [ 4 ] , 10 ) ;
if ( r [ 7 ] . toLowerCase ( ) . indexOf ( 'p' ) !== - 1 ) {
hr _num = chr < 12 ? chr + 12 : chr ;
} else if ( r [ 7 ] . toLowerCase ( ) . indexOf ( 'a' ) !== - 1 ) {
hr _num = chr < 12 ? chr : 0 ;
}
}
2007-10-17 19:53:27 +02:00
var min _num = r [ 5 ] ? r [ 5 ] : 0 ;
var sec _num = r [ 6 ] ? r [ 6 ] : 0 ;
return new Date ( yr _num , mo _num , day _num , hr _num , min _num , sec _num , 0 ) . valueOf ( ) ;
} } ) ,
new TableKit . Sortable . Type ( 'date-eu' , {
pattern : /^\d{2}-\d{2}-\d{4}/i ,
normal : function ( v ) {
if ( ! this . pattern . test ( v ) ) { return 0 ; }
var r = v . match ( /^(\d{2})-(\d{2})-(\d{4})/ ) ;
var yr _num = r [ 3 ] ;
var mo _num = parseInt ( r [ 2 ] , 10 ) - 1 ;
var day _num = r [ 1 ] ;
return new Date ( yr _num , mo _num , day _num ) . valueOf ( ) ;
} } ) ,
new TableKit . Sortable . Type ( 'date-iso' , {
pattern : /[\d]{4}-[\d]{2}-[\d]{2}(?:T[\d]{2}\:[\d]{2}(?:\:[\d]{2}(?:\.[\d]+)?)?(Z|([-+][\d]{2}:[\d]{2})?)?)?/ , // 2005-03-26T19:51:34Z
normal : function ( v ) {
if ( ! this . pattern . test ( v ) ) { return 0 ; }
var d = v . match ( /([\d]{4})(-([\d]{2})(-([\d]{2})(T([\d]{2}):([\d]{2})(:([\d]{2})(\.([\d]+))?)?(Z|(([-+])([\d]{2}):([\d]{2})))?)?)?)?/ ) ;
var offset = 0 ;
var date = new Date ( d [ 1 ] , 0 , 1 ) ;
if ( d [ 3 ] ) { date . setMonth ( d [ 3 ] - 1 ) ; }
if ( d [ 5 ] ) { date . setDate ( d [ 5 ] ) ; }
if ( d [ 7 ] ) { date . setHours ( d [ 7 ] ) ; }
if ( d [ 8 ] ) { date . setMinutes ( d [ 8 ] ) ; }
if ( d [ 10 ] ) { date . setSeconds ( d [ 10 ] ) ; }
if ( d [ 12 ] ) { date . setMilliseconds ( Number ( "0." + d [ 12 ] ) * 1000 ) ; }
if ( d [ 14 ] ) {
offset = ( Number ( d [ 16 ] ) * 60 ) + Number ( d [ 17 ] ) ;
offset *= ( ( d [ 15 ] === '-' ) ? 1 : - 1 ) ;
}
offset -= date . getTimezoneOffset ( ) ;
if ( offset !== 0 ) {
var time = ( Number ( date ) + ( offset * 60 * 1000 ) ) ;
date . setTime ( Number ( time ) ) ;
}
return date . valueOf ( ) ;
} } ) ,
new TableKit . Sortable . Type ( 'date' , {
pattern : /^(?:sun|mon|tue|wed|thu|fri|sat)\,\s\d{1,2}\s(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s\d{4}(?:\s\d{2}\:\d{2}(?:\:\d{2})?(?:\sGMT(?:[+-]\d{4})?)?)?/i , //Mon, 18 Dec 1995 17:28:35 GMT
compare : function ( a , b ) { // must be standard javascript date format
if ( a && b ) {
return TableKit . Sortable . Type . compare ( new Date ( a ) , new Date ( b ) ) ;
} else {
return TableKit . Sortable . Type . compare ( a ? 1 : 0 , b ? 1 : 0 ) ;
}
} } ) ,
new TableKit . Sortable . Type ( 'time' , {
pattern : /^\d{1,2}\:\d{2}(?:\:\d{2})?(?:\s[a|p]m)?$/i ,
compare : function ( a , b ) {
var d = new Date ( ) ;
var ds = d . getMonth ( ) + "/" + d . getDate ( ) + "/" + d . getFullYear ( ) + " " ;
return TableKit . Sortable . Type . compare ( new Date ( ds + a ) , new Date ( ds + b ) ) ;
} } ) ,
new TableKit . Sortable . Type ( 'currency' , {
2008-08-21 17:30:51 +02:00
pattern : /^[$<24> <> <EFBFBD> <EFBFBD> ]/ , // dollar,pound,yen,euro,generic currency symbol
2007-10-17 19:53:27 +02:00
normal : function ( v ) {
return v ? parseFloat ( v . replace ( /[^-\d\.]/g , '' ) ) : 0 ;
} } )
) ;
TableKit . Resizable = {
init : function ( elm , options ) {
var table = $ ( elm ) ;
if ( table . tagName !== "TABLE" ) { return ; }
TableKit . register ( table , Object . extend ( options || { } , { resizable : true } ) ) ;
var cells = TableKit . getHeaderCells ( table ) ;
cells . each ( function ( c ) {
2009-06-08 21:24:28 +02:00
c = $ ( c ) ;
2007-10-17 19:53:27 +02:00
Event . observe ( c , 'mouseover' , TableKit . Resizable . initDetect ) ;
Event . observe ( c , 'mouseout' , TableKit . Resizable . killDetect ) ;
} ) ;
} ,
resize : function ( table , index , w ) {
var cell ;
if ( typeof index === 'number' ) {
if ( ! table || ( table . tagName && table . tagName !== "TABLE" ) ) { return ; }
table = $ ( table ) ;
index = Math . min ( table . rows [ 0 ] . cells . length , index ) ;
index = Math . max ( 1 , index ) ;
index -= 1 ;
cell = ( table . tHead && table . tHead . rows . length > 0 ) ? $ ( table . tHead . rows [ table . tHead . rows . length - 1 ] . cells [ index ] ) : $ ( table . rows [ 0 ] . cells [ index ] ) ;
} else {
cell = $ ( index ) ;
table = table ? $ ( table ) : cell . up ( 'table' ) ;
index = TableKit . getCellIndex ( cell ) ;
}
var pad = parseInt ( cell . getStyle ( 'paddingLeft' ) , 10 ) + parseInt ( cell . getStyle ( 'paddingRight' ) , 10 ) ;
w = Math . max ( w - pad , TableKit . option ( 'minWidth' , table . id ) [ 0 ] ) ;
2008-08-21 17:30:51 +02:00
2007-10-17 19:53:27 +02:00
cell . setStyle ( { 'width' : w + 'px' } ) ;
} ,
initDetect : function ( e ) {
2009-06-08 21:24:28 +02:00
var cell = e . element ( ) ;
if ( cell . tagName != "TD" ) { return ; }
2007-10-17 19:53:27 +02:00
Event . observe ( cell , 'mousemove' , TableKit . Resizable . detectHandle ) ;
Event . observe ( cell , 'mousedown' , TableKit . Resizable . startResize ) ;
} ,
detectHandle : function ( e ) {
2009-06-08 21:24:28 +02:00
e = TableKit . e ( e ) ;
var cell = e . element ( ) ;
if ( TableKit . Resizable . pointerPos ( cell , Event . pointerX ( e ) , Event . pointerY ( e ) ) ) {
2007-10-17 19:53:27 +02:00
cell . addClassName ( TableKit . option ( 'resizeOnHandleClass' , cell . up ( 'table' ) . id ) [ 0 ] ) ;
TableKit . Resizable . _onHandle = true ;
} else {
cell . removeClassName ( TableKit . option ( 'resizeOnHandleClass' , cell . up ( 'table' ) . id ) [ 0 ] ) ;
TableKit . Resizable . _onHandle = false ;
}
} ,
killDetect : function ( e ) {
TableKit . Resizable . _onHandle = false ;
2009-06-08 21:24:28 +02:00
var cell = e . element ( ) ;
2007-10-17 19:53:27 +02:00
Event . stopObserving ( cell , 'mousemove' , TableKit . Resizable . detectHandle ) ;
Event . stopObserving ( cell , 'mousedown' , TableKit . Resizable . startResize ) ;
cell . removeClassName ( TableKit . option ( 'resizeOnHandleClass' , cell . up ( 'table' ) . id ) [ 0 ] ) ;
} ,
startResize : function ( e ) {
2009-06-08 21:24:28 +02:00
if ( ! TableKit . Resizable . _onHandle ) { return ; }
var cell = e . element ( ) ;
2007-10-17 19:53:27 +02:00
Event . stopObserving ( cell , 'mousemove' , TableKit . Resizable . detectHandle ) ;
Event . stopObserving ( cell , 'mousedown' , TableKit . Resizable . startResize ) ;
Event . stopObserving ( cell , 'mouseout' , TableKit . Resizable . killDetect ) ;
TableKit . Resizable . _cell = cell ;
var table = cell . up ( 'table' ) ;
TableKit . Resizable . _tbl = table ;
if ( TableKit . option ( 'showHandle' , table . id ) [ 0 ] ) {
TableKit . Resizable . _handle = $ ( document . createElement ( 'div' ) ) . addClassName ( 'resize-handle' ) . setStyle ( {
2008-08-21 17:30:51 +02:00
'top' : cell . cumulativeOffset ( ) [ 1 ] + 'px' ,
2007-10-17 19:53:27 +02:00
'left' : Event . pointerX ( e ) + 'px' ,
'height' : table . getDimensions ( ) . height + 'px'
} ) ;
document . body . appendChild ( TableKit . Resizable . _handle ) ;
}
Event . observe ( document , 'mousemove' , TableKit . Resizable . drag ) ;
Event . observe ( document , 'mouseup' , TableKit . Resizable . endResize ) ;
Event . stop ( e ) ;
} ,
endResize : function ( e ) {
2009-06-08 21:24:28 +02:00
e = TableKit . e ( e ) ;
2007-10-17 19:53:27 +02:00
var cell = TableKit . Resizable . _cell ;
2009-06-08 21:24:28 +02:00
if ( ! cell ) { return ; }
2008-08-21 17:30:51 +02:00
TableKit . Resizable . resize ( null , cell , ( Event . pointerX ( e ) - cell . cumulativeOffset ( ) [ 0 ] ) ) ;
2007-10-17 19:53:27 +02:00
Event . stopObserving ( document , 'mousemove' , TableKit . Resizable . drag ) ;
Event . stopObserving ( document , 'mouseup' , TableKit . Resizable . endResize ) ;
if ( TableKit . option ( 'showHandle' , TableKit . Resizable . _tbl . id ) [ 0 ] ) {
2009-06-08 21:24:28 +02:00
$$ ( 'div.resize-handle' ) . each ( function ( elm ) {
document . body . removeChild ( elm ) ;
} ) ;
2007-10-17 19:53:27 +02:00
}
Event . observe ( cell , 'mouseout' , TableKit . Resizable . killDetect ) ;
TableKit . Resizable . _tbl = TableKit . Resizable . _handle = TableKit . Resizable . _cell = null ;
Event . stop ( e ) ;
} ,
drag : function ( e ) {
e = TableKit . e ( e ) ;
if ( TableKit . Resizable . _handle === null ) {
try {
2008-08-21 17:30:51 +02:00
TableKit . Resizable . resize ( TableKit . Resizable . _tbl , TableKit . Resizable . _cell , ( Event . pointerX ( e ) - TableKit . Resizable . _cell . cumulativeOffset ( ) [ 0 ] ) ) ;
2007-10-17 19:53:27 +02:00
} catch ( e ) { }
} else {
TableKit . Resizable . _handle . setStyle ( { 'left' : Event . pointerX ( e ) + 'px' } ) ;
}
return false ;
} ,
pointerPos : function ( element , x , y ) {
2008-08-21 17:30:51 +02:00
var offset = $ ( element ) . cumulativeOffset ( ) ;
2007-10-17 19:53:27 +02:00
return ( y >= offset [ 1 ] &&
y < offset [ 1 ] + element . offsetHeight &&
x >= offset [ 0 ] + element . offsetWidth - 5 &&
x < offset [ 0 ] + element . offsetWidth ) ;
} ,
_onHandle : false ,
_cell : null ,
_tbl : null ,
_handle : null
} ;
TableKit . Editable = {
init : function ( elm , options ) {
var table = $ ( elm ) ;
if ( table . tagName !== "TABLE" ) { return ; }
TableKit . register ( table , Object . extend ( options || { } , { editable : true } ) ) ;
Event . observe ( table . tBodies [ 0 ] , 'click' , TableKit . Editable . _editCell ) ;
} ,
_editCell : function ( e ) {
e = TableKit . e ( e ) ;
var cell = Event . findElement ( e , 'td' ) ;
2008-08-21 17:30:51 +02:00
if ( cell ) {
TableKit . Editable . editCell ( null , cell , null , e ) ;
} else {
return false ;
}
2007-10-17 19:53:27 +02:00
} ,
2008-08-21 17:30:51 +02:00
editCell : function ( table , index , cindex , event ) {
2007-10-17 19:53:27 +02:00
var cell , row ;
if ( typeof index === 'number' ) {
if ( ! table || ( table . tagName && table . tagName !== "TABLE" ) ) { return ; }
table = $ ( table ) ;
index = Math . min ( table . tBodies [ 0 ] . rows . length , index ) ;
index = Math . max ( 1 , index ) ;
index -= 1 ;
cindex = Math . min ( table . rows [ 0 ] . cells . length , cindex ) ;
cindex = Math . max ( 1 , cindex ) ;
cindex -= 1 ;
row = $ ( table . tBodies [ 0 ] . rows [ index ] ) ;
cell = $ ( row . cells [ cindex ] ) ;
} else {
2008-08-21 17:30:51 +02:00
cell = $ ( event ? Event . findElement ( event , 'td' ) : index ) ;
2007-10-17 19:53:27 +02:00
table = ( table && table . tagName && table . tagName !== "TABLE" ) ? $ ( table ) : cell . up ( 'table' ) ;
row = cell . up ( 'tr' ) ;
}
var op = TableKit . option ( 'noEditClass' , table . id ) ;
if ( cell . hasClassName ( op . noEditClass ) ) { return ; }
var head = $ ( TableKit . getHeaderCells ( table , cell ) [ TableKit . getCellIndex ( cell ) ] ) ;
if ( head . hasClassName ( op . noEditClass ) ) { return ; }
2008-08-21 17:30:51 +02:00
var data = TableKit . getCellData ( cell ) ;
2007-10-17 19:53:27 +02:00
if ( data . active ) { return ; }
data . htmlContent = cell . innerHTML ;
2008-08-21 17:30:51 +02:00
var ftype = TableKit . Editable . getCellEditor ( null , null , head ) ;
ftype . edit ( cell , event ) ;
data . active = true ;
} ,
getCellEditor : function ( cell , table , head ) {
var head = head ? head : $ ( TableKit . getHeaderCells ( table , cell ) [ TableKit . getCellIndex ( cell ) ] ) ;
var ftype = TableKit . Editable . types [ 'text-input' ] ;
2007-10-17 19:53:27 +02:00
if ( head . id && TableKit . Editable . types [ head . id ] ) {
ftype = TableKit . Editable . types [ head . id ] ;
} else {
2008-08-21 17:30:51 +02:00
var n = $w ( head . className ) . detect ( function ( n ) {
2007-10-17 19:53:27 +02:00
return ( TableKit . Editable . types [ n ] ) ? true : false ;
} ) ;
ftype = n ? TableKit . Editable . types [ n ] : ftype ;
}
2008-08-21 17:30:51 +02:00
return ftype ;
2007-10-17 19:53:27 +02:00
} ,
types : { } ,
addCellEditor : function ( o ) {
if ( o && o . name ) { TableKit . Editable . types [ o . name ] = o ; }
}
} ;
TableKit . Editable . CellEditor = Class . create ( ) ;
TableKit . Editable . CellEditor . prototype = {
initialize : function ( name , options ) {
this . name = name ;
this . options = Object . extend ( {
element : 'input' ,
attributes : { name : 'value' , type : 'text' } ,
selectOptions : [ ] ,
showSubmit : true ,
submitText : 'OK' ,
showCancel : true ,
cancelText : 'Cancel' ,
ajaxURI : null ,
ajaxOptions : null
} , options || { } ) ;
} ,
edit : function ( cell ) {
cell = $ ( cell ) ;
var op = this . options ;
var table = cell . up ( 'table' ) ;
var form = $ ( document . createElement ( "form" ) ) ;
form . id = cell . id + '-form' ;
form . addClassName ( TableKit . option ( 'formClassName' , table . id ) [ 0 ] ) ;
form . onsubmit = this . _submit . bindAsEventListener ( this ) ;
var field = document . createElement ( op . element ) ;
$H ( op . attributes ) . each ( function ( v ) {
field [ v . key ] = v . value ;
} ) ;
switch ( op . element ) {
case 'input' :
case 'textarea' :
field . value = TableKit . getCellText ( cell ) ;
break ;
case 'select' :
var txt = TableKit . getCellText ( cell ) ;
$A ( op . selectOptions ) . each ( function ( v ) {
field . options [ field . options . length ] = new Option ( v [ 0 ] , v [ 1 ] ) ;
if ( txt === v [ 1 ] ) {
field . options [ field . options . length - 1 ] . selected = 'selected' ;
}
} ) ;
break ;
}
form . appendChild ( field ) ;
if ( op . element === 'textarea' ) {
form . appendChild ( document . createElement ( "br" ) ) ;
}
if ( op . showSubmit ) {
var okButton = document . createElement ( "input" ) ;
okButton . type = "submit" ;
okButton . value = op . submitText ;
okButton . className = 'editor_ok_button' ;
form . appendChild ( okButton ) ;
}
if ( op . showCancel ) {
var cancelLink = document . createElement ( "a" ) ;
cancelLink . href = "#" ;
cancelLink . appendChild ( document . createTextNode ( op . cancelText ) ) ;
cancelLink . onclick = this . _cancel . bindAsEventListener ( this ) ;
cancelLink . className = 'editor_cancel' ;
form . appendChild ( cancelLink ) ;
}
cell . innerHTML = '' ;
cell . appendChild ( form ) ;
} ,
_submit : function ( e ) {
var cell = Event . findElement ( e , 'td' ) ;
var form = Event . findElement ( e , 'form' ) ;
Event . stop ( e ) ;
this . submit ( cell , form ) ;
} ,
submit : function ( cell , form ) {
var op = this . options ;
form = form ? form : cell . down ( 'form' ) ;
var head = $ ( TableKit . getHeaderCells ( null , cell ) [ TableKit . getCellIndex ( cell ) ] ) ;
var row = cell . up ( 'tr' ) ;
var table = cell . up ( 'table' ) ;
var s = '&row=' + ( TableKit . getRowIndex ( row ) + 1 ) + '&cell=' + ( TableKit . getCellIndex ( cell ) + 1 ) + '&id=' + row . id + '&field=' + head . id + '&' + Form . serialize ( form ) ;
this . ajax = new Ajax . Updater ( cell , op . ajaxURI || TableKit . option ( 'editAjaxURI' , table . id ) [ 0 ] , Object . extend ( op . ajaxOptions || TableKit . option ( 'editAjaxOptions' , table . id ) [ 0 ] , {
postBody : s ,
onComplete : function ( ) {
2008-08-21 17:30:51 +02:00
var data = TableKit . getCellData ( cell ) ;
2007-10-17 19:53:27 +02:00
data . active = false ;
data . refresh = true ; // mark cell cache for refreshing, in case cell contents has changed and sorting is applied
}
} ) ) ;
} ,
_cancel : function ( e ) {
var cell = Event . findElement ( e , 'td' ) ;
Event . stop ( e ) ;
this . cancel ( cell ) ;
} ,
cancel : function ( cell ) {
this . ajax = null ;
2008-08-21 17:30:51 +02:00
var data = TableKit . getCellData ( cell ) ;
2007-10-17 19:53:27 +02:00
cell . innerHTML = data . htmlContent ;
data . htmlContent = '' ;
data . active = false ;
} ,
ajax : null
} ;
TableKit . Editable . textInput = function ( n , attributes ) {
TableKit . Editable . addCellEditor ( new TableKit . Editable . CellEditor ( n , {
element : 'input' ,
attributes : Object . extend ( { name : 'value' , type : 'text' } , attributes || { } )
} ) ) ;
} ;
TableKit . Editable . textInput ( 'text-input' ) ;
TableKit . Editable . multiLineInput = function ( n , attributes ) {
TableKit . Editable . addCellEditor ( new TableKit . Editable . CellEditor ( n , {
element : 'textarea' ,
attributes : Object . extend ( { name : 'value' , rows : '5' , cols : '20' } , attributes || { } )
} ) ) ;
} ;
TableKit . Editable . multiLineInput ( 'multi-line-input' ) ;
TableKit . Editable . selectInput = function ( n , attributes , selectOptions ) {
TableKit . Editable . addCellEditor ( new TableKit . Editable . CellEditor ( n , {
element : 'select' ,
attributes : Object . extend ( { name : 'value' } , attributes || { } ) ,
'selectOptions' : selectOptions
} ) ) ;
} ;
/ *
TableKit . Bench = {
bench : [ ] ,
start : function ( ) {
TableKit . Bench . bench [ 0 ] = new Date ( ) . getTime ( ) ;
} ,
end : function ( s ) {
TableKit . Bench . bench [ 1 ] = new Date ( ) . getTime ( ) ;
alert ( s + ' ' + ( ( TableKit . Bench . bench [ 1 ] - TableKit . Bench . bench [ 0 ] ) / 1000 ) + ' seconds.' ) //console.log(s + ' ' + ((TableKit.Bench.bench[1]-TableKit.Bench.bench[0])/1000)+' seconds.')
TableKit . Bench . bench = [ ] ;
}
} * /
2008-08-21 17:30:51 +02:00
document . observe ( "dom:loaded" , TableKit . load ) ;