1
0
Fork 0
mirror of https://github.com/koalyptus/TableFilter.git synced 2024-05-13 11:56:46 +02:00

Fixed grid layout bug with IE

This commit is contained in:
Max Guglielmi 2014-11-23 21:31:55 +11:00
parent 8774c670ff
commit e07aa52df9
13 changed files with 1268 additions and 534 deletions

View file

@ -0,0 +1,321 @@
/*------------------------------------------------------------------------
- HTML Table Filter Generator Sorting Feature
- TF Adapter v2.1 for WebFX Sortable Table 1.12 (Erik Arvidsson)
- By Max Guglielmi (tablefilter.free.fr)
- Licensed under the MIT License
--------------------------------------------------------------------------
Copyright (c) 2009-2012 Max Guglielmi
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.
------------------------------------------------------------------------
- Changelog:
1.1 [30-09-09]
When table is paged now the whole table is sorted and not
only the current page
1.2 [05-12-09]
Added on_before_sort and on_after_sort callback functions
1.3 [06-09-10]
Added IP adresses sort
1.4 [22-01-11]
Added DDMMMYYYY date format support
1.5 [20-02-11]
Image folder and sort icon can now be set in configuration
object
1.6 [06-08-11]
Added on_sort_loaded callback function
1.7 [20-08-11]
Added sort arrow css classes properties
Added sort custom key property allowing custom sorts
Added AddSortType public method
1.8 [25-09-11]
Bug fix: sort did not take into account results per page changes
1.9 [03-03-12]
Bug fix: custom value attribute value was read only by Firefox
2.0 [08-04-12]
Bug fix: zebra rows background are no longer inverted after sort
2.1 [25-08-12]
Bug fix: IE9 did not sort columns correctly
------------------------------------------------------------------------*/
TF.prototype.SetSortTable = function(){
var o = this; //TF object
var f = o.fObj; //TF config object
var isTFPaged = false;
//edit .sort-arrow.descending / .sort-arrow.ascending in filtergrid.css to reflect any path change
o.sortImgPath = f.sort_images_path != undefined ? f.sort_images_path : o.themesPath;
o.sortImgBlank = f.sort_image_blank != undefined ? f.sort_image_blank : 'blank.png';
o.sortImgClassName = f.sort_image_class_name != undefined ? f.sort_image_class_name : 'sort-arrow';
o.sortImgAscClassName = f.sort_image_asc_class_name != undefined ? f.sort_image_asc_class_name : 'ascending';
o.sortImgDescClassName = f.sort_image_desc_class_name != undefined ? f.sort_image_desc_class_name : 'descending';
o.sortCustomKey = f.sort_custom_key != undefined ? f.sort_custom_key : '_sortKey'; //cell attribute storing custom key
/*** TF additional events ***/
//additional paging events for alternating bg issue
o.Evt._Paging.nextEvt = function(){ if(o.sorted && o.alternateBgs) o.Filter(); }
o.Evt._Paging.prevEvt = o.Evt._Paging.nextEvt;
o.Evt._Paging.firstEvt = o.Evt._Paging.nextEvt;
o.Evt._Paging.lastEvt = o.Evt._Paging.nextEvt;
o.Evt._OnSlcPagesChangeEvt = o.Evt._Paging.nextEvt;
/*** ***/
/*** Extension events ***/
//callback invoked after sort is loaded and instanciated
o.onSortLoaded = tf_IsFn(f.on_sort_loaded) ? f.on_sort_loaded : null;
//callback invoked before table is sorted
o.onBeforeSort = tf_IsFn(f.on_before_sort) ? f.on_before_sort : null;
//callback invoked after table is sorted
o.onAfterSort = tf_IsFn(f.on_after_sort) ? f.on_after_sort : null;
/*** SortableTable ***/
//in case SortableTable class is missing (sortabletable.js)
if((typeof SortableTable)=='undefined'){ return; }
//overrides headerOnclick method in order to handle th
SortableTable.prototype.headerOnclick = function (e) {
if(!o.sort) return; // TF adaptation
var el = e.target || e.srcElement; // find Header element
while (el.tagName != 'TD' && el.tagName != 'TH') // TF adaptation
el = el.parentNode;
this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
};
//overrides getCellIndex IE returns wrong cellIndex when columns are hidden
SortableTable.getCellIndex = function (oTd) {
var cells = oTd.parentNode.cells,
l = cells.length, i;
for (i = 0; cells[i] != oTd && i < l; i++)
;
return i;
};
//overrides initHeader in order to handle filters row position
SortableTable.prototype.initHeader = function (oSortTypes) {
if (!this.tHead) return;
this.headersRow = o.headersRow; // TF adaptation
var cells = this.tHead.rows[this.headersRow].cells; // TF adaptation
var doc = this.tHead.ownerDocument || this.tHead.document;
this.sortTypes = oSortTypes || [];
var l = cells.length;
var img, c;
for (var i = 0; i < l; i++) {
c = cells[i];
if (this.sortTypes[i] != null && this.sortTypes[i] != 'None') {
c.style.cursor = 'pointer';
img = tf_CreateElm('img',['src', o.sortImgPath + o.sortImgBlank]);
c.appendChild(img);
if (this.sortTypes[i] != null)
c.setAttribute( '_sortType', this.sortTypes[i]);
tf_AddEvent(c, 'click', this._headerOnclick);
} else {
c.setAttribute( '_sortType', oSortTypes[i] );
c._sortType = 'None';
}
}
this.updateHeaderArrows();
};
//overrides updateHeaderArrows in order to handle arrows
SortableTable.prototype.updateHeaderArrows = function () {
var cells, l, img;
if(o.sortConfig.asyncSort && o.sortConfig.triggerIds!=null){//external headers
var triggers = o.sortConfig.triggerIds;
cells = [], l = triggers.length;
for(var j=0; j<triggers.length; j++)
cells.push(tf_Id(triggers[j]));
} else {
if (!this.tHead) return;
cells = this.tHead.rows[this.headersRow].cells; //TF implementation instead
l = cells.length;
}
for (var i = 0; i < l; i++) {
if (cells[i].getAttribute('_sortType') != null && cells[i].getAttribute('_sortType') != 'None') {
img = cells[i].lastChild || cells[i];
if(img.nodeName.tf_LCase()!='img'){//creates images
img = tf_CreateElm('img',['src', o.sortImgPath + o.sortImgBlank]);
cells[i].appendChild(img);
}
if (i == this.sortColumn)
img.className = o.sortImgClassName +' '+ (this.descending ? o.sortImgDescClassName : o.sortImgAscClassName);
else img.className = o.sortImgClassName;
}
}
};
//overrides getRowValue for custom key value feature
SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
// if we have defined a custom getRowValue use that
if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
var c = oRow.cells[nColumn];
var s = SortableTable.getInnerText(c);
return this.getValueFromString(s, sType);
};
//overrides getInnerText in order to avoid Firefox unexpected sorting behaviour with untrimmed text elements
SortableTable.getInnerText = function (oNode) {
if (oNode.getAttribute(o.sortCustomKey) != null) //custom sort key
return oNode.getAttribute(o.sortCustomKey);
else return tf_GetNodeText(oNode);
};
//sort types
var sortTypes = [];
for(var i=0; i<o.nbCells; i++){
var colType;
if(this.sortConfig.sortTypes!=null && this.sortConfig.sortTypes[i]!=null){
colType = this.sortConfig.sortTypes[i].tf_LCase();
if(colType=='none') colType = 'None';
} else {//resolves column types
if(o.hasColNbFormat && o.colNbFormat[i]!=null)
colType = o.colNbFormat[i].tf_LCase();
//colType = 'Number';
else if(o.hasColDateType && o.colDateType[i]!=null)
colType = o.colDateType[i].tf_LCase()+'date';
else colType = 'String';
}
sortTypes.push(colType);
}
//Public TF method to add sort type
this.AddSortType = function(){ SortableTable.prototype.addSortType(arguments[0], arguments[1], arguments[2], arguments[3]); };
//Custom sort types
this.AddSortType('number', Number);
this.AddSortType('caseinsensitivestring', SortableTable.toUpperCase);
this.AddSortType('date', SortableTable.toDate);
this.AddSortType('string');
this.AddSortType('us', usNumberConverter);
this.AddSortType('eu', euNumberConverter);
this.AddSortType('dmydate', dmyDateConverter);
this.AddSortType('ymddate', ymdDateConverter);
this.AddSortType('mdydate', mdyDateConverter);
this.AddSortType('ddmmmyyyydate', ddmmmyyyyDateConverter);
this.AddSortType('ipaddress', ipAddress, sortIP);
this.st = new SortableTable(this.tbl,sortTypes);
/*** external table headers adapter ***/
if(this.sortConfig.asyncSort && this.sortConfig.triggerIds!=null){
var triggers = this.sortConfig.triggerIds;
for(var j=0; j<triggers.length; j++){
if(triggers[j]==null) continue;
var trigger = tf_Id(triggers[j]);
if(trigger){
trigger.style.cursor = 'pointer';
trigger.onclick = function(){
if(o.sort)
o.st.asyncSort( triggers.tf_IndexByValue(this.id, true) );
}
trigger.setAttribute( '_sortType', sortTypes[j] );
}
}
}
/*** ***/
//Column sort at start
if(this.sortConfig.sortCol)
this.st.sort( this.sortConfig.sortCol[0], this.sortConfig.sortCol[1] );
this.isSortEnabled = true; //sort is set
if(this.onSortLoaded) this.onSortLoaded.call(null, this, this.st);
/*** Sort events ***/
this.st.onbeforesort = function(){
if(o.onBeforeSort) o.onBeforeSort.call(null, o, o.st.sortColumn);
o.Sort(); //TF method
/*** sort behaviour for paging ***/
if(o.paging){
isTFPaged = true;
o.paging = false;
o.RemovePaging();
}
}//onbeforesort
this.st.onsort = function(){
o.sorted = true;//table is sorted
//rows alternating bg issue
if(o.alternateBgs){
var rows = o.tbl.rows, c = 0;
function setClass(row, i, removeOnly){
if(removeOnly == undefined) removeOnly = false;
tf_removeClass(row, o.rowBgEvenCssClass);
tf_removeClass(row, o.rowBgOddCssClass);
if(!removeOnly)
tf_addClass(row, i % 2 ? o.rowBgOddCssClass : o.rowBgEvenCssClass);
}
for (var i = o.refRow; i < o.nbRows; i++) {
var isRowValid = rows[i].getAttribute('validRow');
if(o.paging && rows[i].style.display == ''){
setClass(rows[i], c);
c++;
} else {
if((isRowValid=='true' || isRowValid==null) && rows[i].style.display == ''){
setClass(rows[i], c);
c++;
} else setClass(rows[i], c, true);
}
}
}
//sort behaviour for paging
if(isTFPaged){
if(o.hasResultsPerPage)
o.fObj.paging_length = o.resultsPerPageSlc.options[o.resultsPerPageSlc.selectedIndex].value;
o.AddPaging(false);
o.SetPage(o.currentPageNb);
isTFPaged = false;
}
if(o.onAfterSort) o.onAfterSort.call(null,o,o.st.sortColumn);
}//onsort
}
//Converter fns
function usNumberConverter(s){ return tf_removeNbFormat(s,'us'); }
function euNumberConverter(s){ return tf_removeNbFormat(s,'eu'); }
function dateConverter(s, format){ return tf_formatDate(s, format); }
function dmyDateConverter(s){ return dateConverter(s,'DMY'); }
function mdyDateConverter(s){ return dateConverter(s,'MDY'); }
function ymdDateConverter(s){ return dateConverter(s,'YMD'); }
function ddmmmyyyyDateConverter(s){ return dateConverter(s,'DDMMMYYYY'); }
function ipAddress(val){
var vals = val.split('.');
for (x in vals) {
val = vals[x];
while (3 > val.length) val = '0'+val;
vals[x] = val;
}
val = vals.join('.');
return val;
}
function sortIP(a,b){
var aa = ipAddress(a.value.tf_LCase());
var bb = ipAddress(b.value.tf_LCase());
if (aa==bb) return 0;
else if (aa<bb) return -1;
else return 1;
}

2
dist/filtergrid.css vendored
View file

@ -1,6 +1,6 @@
/*------------------------------------------------------------------------
- TableFilter stylesheet by Max Guglielmi
- (build date: Sun Nov 23 2014 14:31:03)
- (build date: Sun Nov 23 2014 21:28:33)
- Edit below for your projects' needs
------------------------------------------------------------------------*/

4
dist/tablefilter.js vendored

File diff suppressed because one or more lines are too long

View file

@ -4,13 +4,12 @@
var Event = {
add: function(obj, type, func, capture){
if(obj.attachEvent){
obj.attachEvent('on'+type, func);
if(obj.addEventListener){
obj.addEventListener(type, func, capture);
}
else if(obj.addEventListener){
obj.addEventListener(type, func,
(capture===undefined ? false : capture));
} else{
else if(obj.attachEvent){
obj.attachEvent('on'+type, func);
} else {
obj['on'+type] = func;
}
},
@ -19,8 +18,7 @@ var Event = {
obj.detachEvent('on'+type,func);
}
else if(obj.removeEventListener){
obj.removeEventListener(type, func,
(capture===undefined ? false : capture));
obj.removeEventListener(type, func, capture);
} else {
obj['on'+type] = null;
}

View file

@ -5,6 +5,10 @@ import {Event} from '../event';
export class GridLayout{
/**
* Grid layout, table with fixed headers
* @param {Object} tf TableFilter instance
*/
constructor(tf) {
var f = tf.fObj;
@ -37,14 +41,23 @@ export class GridLayout{
this.gridColResizerPath = f.grid_cont_col_resizer_path ||
this.basePath+'TFExt_ColsResizer/TFExt_ColsResizer.js';
this.gridColElms = [];
this.tf = tf;
}
/**
* Generates a grid with fixed headers
*/
init(){
var tf = this.tf;
var f = tf.fObj;
var tbl = tf.tbl;
if(!tf.gridLayout){
return;
}
tf.isExternalFlt = true;
// default width of 100px if column widths not set
@ -171,21 +184,21 @@ export class GridLayout{
this.headTbl.cellPadding = tbl.cellPadding;
this.headTbl.cellSpacing = tbl.cellSpacing;
//Headers container width
this.headTblCont.style.width = this.tblCont.clientWidth+'px';
//content table without headers needs col widths to be reset
tf.SetColWidths();
//Headers container width
this.headTblCont.style.width = this.tblCont.clientWidth+'px';
tbl.style.width = '';
if(Helpers.isIE()){
this.headTbl.style.width = '';
}
// if(Helpers.isIE()){
// this.headTbl.style.width = '';
// }
//scroll synchronisation
var o = this; //TF object
var o = this;
Event.add(this.tblCont, 'scroll', function(){
Event.add(this.tblCont, 'scroll', function(evt){
//this = scroll element
var scrollLeft = this.scrollLeft;
o.headTblCont.scrollLeft = scrollLeft;
@ -244,17 +257,18 @@ export class GridLayout{
//Cols generation for all browsers excepted IE<=7
o.tblHasColTag = Dom.tag(tbl, 'col').length > 0 ? true : false;
if(!Helpers.isIE()){
// if(!Helpers.isIE()){
//Col elements are enough to keep column widths after sorting and
//filtering
var createColTags = function(o){
if(!o){
return;
}
for(var k=(o.nbCells-1); k>=0; k--){
var col = Dom.create( 'col', ['id', o.id+'_col_'+k]);
for(var k=(tf.nbCells-1); k>=0; k--){
var col = Dom.create('col', ['id', tf.id+'_col_'+k]);
tbl.firstChild.parentNode.insertBefore(col, tbl.firstChild);
col.style.width = o.colWidth[k];
col.style.width = tf.colWidth[k];
o.gridColElms[k] = col;
}
o.tblHasColTag = true;
@ -262,63 +276,63 @@ export class GridLayout{
if(!o.tblHasColTag){
createColTags(o);
} else {
var cols = Dom.tag(tbl,'col');
for(var ii=0; ii<o.nbCells; ii++){
cols[ii].setAttribute('id', o.id+'_col_'+ii);
cols[ii].style.width = o.colWidth[ii];
var cols = Dom.tag(tbl, 'col');
for(var ii=0; ii<tf.nbCells; ii++){
cols[ii].setAttribute('id', tf.id+'_col_'+ii);
cols[ii].style.width = tf.colWidth[ii];
o.gridColElms.push(cols[ii]);
}
}
}
// }
//IE <= 7 needs an additional row for widths as col element width is
//not enough...
if(Helpers.isIE()){
var tbody = Dom.tag(tbl,'tbody'),
r;
if( tbody.length>0 ){
r = tbody[0].insertRow(0);
} else{
r = tbl.insertRow(0);
}
r.style.height = '0px';
for(var x=0; x<o.nbCells; x++){
var col = Dom.create('td', ['id', o.id+'_col_'+x]);
col.style.width = o.colWidth[x];
tbl.rows[1].cells[x].style.width = '';
r.appendChild(col);
o.gridColElms.push(col);
}
this.hasGridWidthsRow = true;
//Data table row with widths expressed
o.leadColWidthsRow = tbl.rows[0];
o.leadColWidthsRow.setAttribute('validRow', 'false');
// if(Helpers.isIE()){
// var tbody = Dom.tag(tbl,'tbody'),
// r;
// if( tbody.length>0 ){
// r = tbody[0].insertRow(0);
// } else{
// r = tbl.insertRow(0);
// }
// r.style.height = '0px';
// for(var x=0; x<o.nbCells; x++){
// var col = Dom.create('td', ['id', o.id+'_col_'+x]);
// col.style.width = o.colWidth[x];
// tbl.rows[1].cells[x].style.width = '';
// r.appendChild(col);
// o.gridColElms.push(col);
// }
// tf.hasGridWidthsRow = true;
// //Data table row with widths expressed
// o.leadColWidthsRow = tbl.rows[0];
// o.leadColWidthsRow.setAttribute('validRow', 'false');
var beforeSortFn = Types.isFn(f.on_before_sort) ?
f.on_before_sort : null;
f.on_before_sort = function(o, colIndex){
o.leadColWidthsRow.setAttribute('validRow', 'false');
if(beforeSortFn){
beforeSortFn.call(null, o, colIndex);
}
};
// var beforeSortFn = Types.isFn(f.on_before_sort) ?
// f.on_before_sort : null;
// f.on_before_sort = function(o, colIndex){
// o.leadColWidthsRow.setAttribute('validRow', 'false');
// if(beforeSortFn){
// beforeSortFn.call(null, o, colIndex);
// }
// };
var afterSortFn = Types.isFn(f.on_after_sort) ?
f.on_after_sort : null;
f.on_after_sort = function(o,colIndex){
if(o.leadColWidthsRow.rowIndex !== 0){
var r = o.leadColWidthsRow;
if(tbody.length>0){
tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
} else {
tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
}
}
if(afterSortFn){
afterSortFn.call(null, o, colIndex);
}
};
}
// var afterSortFn = Types.isFn(f.on_after_sort) ?
// f.on_after_sort : null;
// f.on_after_sort = function(o,colIndex){
// if(o.leadColWidthsRow.rowIndex !== 0){
// var r = o.leadColWidthsRow;
// if(tbody.length>0){
// tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
// } else {
// tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
// }
// }
// if(afterSortFn){
// afterSortFn.call(null, o, colIndex);
// }
// };
// }
var afterColResizedFn = Types.isFn(f.on_after_col_resized) ?
f.on_after_col_resized : null;
@ -333,11 +347,11 @@ export class GridLayout{
var thCW = o.crWColsRow.cells[colIndex].clientWidth;
var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
if(Helpers.isIE()){
tbl.style.width = o.headTbl.clientWidth+'px';
}
// if(Helpers.isIE()){
// tbl.style.width = o.headTbl.clientWidth+'px';
// }
if(thCW != tdCW && !Helpers.isIE()){
if(thCW != tdCW /*&& !Helpers.isIE()*/){
o.headTbl.style.width = tbl.clientWidth+'px';
}
@ -351,9 +365,12 @@ export class GridLayout{
}
// Re-adjust reference row
tf.refRow = Helpers.isIE() ? (tf.refRow+1) : 0;
//tf.refRow = Helpers.isIE() ? (tf.refRow+1) : 0;
}
/**
* Removes the grid layout
*/
destroy(){
var tf = this.tf;
var tbl = tf.tbl;

View file

@ -0,0 +1,321 @@
/*------------------------------------------------------------------------
- HTML Table Filter Generator Sorting Feature
- TF Adapter v2.1 for WebFX Sortable Table 1.12 (Erik Arvidsson)
- By Max Guglielmi (tablefilter.free.fr)
- Licensed under the MIT License
--------------------------------------------------------------------------
Copyright (c) 2009-2012 Max Guglielmi
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.
------------------------------------------------------------------------
- Changelog:
1.1 [30-09-09]
When table is paged now the whole table is sorted and not
only the current page
1.2 [05-12-09]
Added on_before_sort and on_after_sort callback functions
1.3 [06-09-10]
Added IP adresses sort
1.4 [22-01-11]
Added DDMMMYYYY date format support
1.5 [20-02-11]
Image folder and sort icon can now be set in configuration
object
1.6 [06-08-11]
Added on_sort_loaded callback function
1.7 [20-08-11]
Added sort arrow css classes properties
Added sort custom key property allowing custom sorts
Added AddSortType public method
1.8 [25-09-11]
Bug fix: sort did not take into account results per page changes
1.9 [03-03-12]
Bug fix: custom value attribute value was read only by Firefox
2.0 [08-04-12]
Bug fix: zebra rows background are no longer inverted after sort
2.1 [25-08-12]
Bug fix: IE9 did not sort columns correctly
------------------------------------------------------------------------*/
TF.prototype.SetSortTable = function(){
var o = this; //TF object
var f = o.fObj; //TF config object
var isTFPaged = false;
//edit .sort-arrow.descending / .sort-arrow.ascending in filtergrid.css to reflect any path change
o.sortImgPath = f.sort_images_path != undefined ? f.sort_images_path : o.themesPath;
o.sortImgBlank = f.sort_image_blank != undefined ? f.sort_image_blank : 'blank.png';
o.sortImgClassName = f.sort_image_class_name != undefined ? f.sort_image_class_name : 'sort-arrow';
o.sortImgAscClassName = f.sort_image_asc_class_name != undefined ? f.sort_image_asc_class_name : 'ascending';
o.sortImgDescClassName = f.sort_image_desc_class_name != undefined ? f.sort_image_desc_class_name : 'descending';
o.sortCustomKey = f.sort_custom_key != undefined ? f.sort_custom_key : '_sortKey'; //cell attribute storing custom key
/*** TF additional events ***/
//additional paging events for alternating bg issue
o.Evt._Paging.nextEvt = function(){ if(o.sorted && o.alternateBgs) o.Filter(); }
o.Evt._Paging.prevEvt = o.Evt._Paging.nextEvt;
o.Evt._Paging.firstEvt = o.Evt._Paging.nextEvt;
o.Evt._Paging.lastEvt = o.Evt._Paging.nextEvt;
o.Evt._OnSlcPagesChangeEvt = o.Evt._Paging.nextEvt;
/*** ***/
/*** Extension events ***/
//callback invoked after sort is loaded and instanciated
o.onSortLoaded = tf_IsFn(f.on_sort_loaded) ? f.on_sort_loaded : null;
//callback invoked before table is sorted
o.onBeforeSort = tf_IsFn(f.on_before_sort) ? f.on_before_sort : null;
//callback invoked after table is sorted
o.onAfterSort = tf_IsFn(f.on_after_sort) ? f.on_after_sort : null;
/*** SortableTable ***/
//in case SortableTable class is missing (sortabletable.js)
if((typeof SortableTable)=='undefined'){ return; }
//overrides headerOnclick method in order to handle th
SortableTable.prototype.headerOnclick = function (e) {
if(!o.sort) return; // TF adaptation
var el = e.target || e.srcElement; // find Header element
while (el.tagName != 'TD' && el.tagName != 'TH') // TF adaptation
el = el.parentNode;
this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
};
//overrides getCellIndex IE returns wrong cellIndex when columns are hidden
SortableTable.getCellIndex = function (oTd) {
var cells = oTd.parentNode.cells,
l = cells.length, i;
for (i = 0; cells[i] != oTd && i < l; i++)
;
return i;
};
//overrides initHeader in order to handle filters row position
SortableTable.prototype.initHeader = function (oSortTypes) {
if (!this.tHead) return;
this.headersRow = o.headersRow; // TF adaptation
var cells = this.tHead.rows[this.headersRow].cells; // TF adaptation
var doc = this.tHead.ownerDocument || this.tHead.document;
this.sortTypes = oSortTypes || [];
var l = cells.length;
var img, c;
for (var i = 0; i < l; i++) {
c = cells[i];
if (this.sortTypes[i] != null && this.sortTypes[i] != 'None') {
c.style.cursor = 'pointer';
img = tf_CreateElm('img',['src', o.sortImgPath + o.sortImgBlank]);
c.appendChild(img);
if (this.sortTypes[i] != null)
c.setAttribute( '_sortType', this.sortTypes[i]);
tf_AddEvent(c, 'click', this._headerOnclick);
} else {
c.setAttribute( '_sortType', oSortTypes[i] );
c._sortType = 'None';
}
}
this.updateHeaderArrows();
};
//overrides updateHeaderArrows in order to handle arrows
SortableTable.prototype.updateHeaderArrows = function () {
var cells, l, img;
if(o.sortConfig.asyncSort && o.sortConfig.triggerIds!=null){//external headers
var triggers = o.sortConfig.triggerIds;
cells = [], l = triggers.length;
for(var j=0; j<triggers.length; j++)
cells.push(tf_Id(triggers[j]));
} else {
if (!this.tHead) return;
cells = this.tHead.rows[this.headersRow].cells; //TF implementation instead
l = cells.length;
}
for (var i = 0; i < l; i++) {
if (cells[i].getAttribute('_sortType') != null && cells[i].getAttribute('_sortType') != 'None') {
img = cells[i].lastChild || cells[i];
if(img.nodeName.tf_LCase()!='img'){//creates images
img = tf_CreateElm('img',['src', o.sortImgPath + o.sortImgBlank]);
cells[i].appendChild(img);
}
if (i == this.sortColumn)
img.className = o.sortImgClassName +' '+ (this.descending ? o.sortImgDescClassName : o.sortImgAscClassName);
else img.className = o.sortImgClassName;
}
}
};
//overrides getRowValue for custom key value feature
SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
// if we have defined a custom getRowValue use that
if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
var c = oRow.cells[nColumn];
var s = SortableTable.getInnerText(c);
return this.getValueFromString(s, sType);
};
//overrides getInnerText in order to avoid Firefox unexpected sorting behaviour with untrimmed text elements
SortableTable.getInnerText = function (oNode) {
if (oNode.getAttribute(o.sortCustomKey) != null) //custom sort key
return oNode.getAttribute(o.sortCustomKey);
else return tf_GetNodeText(oNode);
};
//sort types
var sortTypes = [];
for(var i=0; i<o.nbCells; i++){
var colType;
if(this.sortConfig.sortTypes!=null && this.sortConfig.sortTypes[i]!=null){
colType = this.sortConfig.sortTypes[i].tf_LCase();
if(colType=='none') colType = 'None';
} else {//resolves column types
if(o.hasColNbFormat && o.colNbFormat[i]!=null)
colType = o.colNbFormat[i].tf_LCase();
//colType = 'Number';
else if(o.hasColDateType && o.colDateType[i]!=null)
colType = o.colDateType[i].tf_LCase()+'date';
else colType = 'String';
}
sortTypes.push(colType);
}
//Public TF method to add sort type
this.AddSortType = function(){ SortableTable.prototype.addSortType(arguments[0], arguments[1], arguments[2], arguments[3]); };
//Custom sort types
this.AddSortType('number', Number);
this.AddSortType('caseinsensitivestring', SortableTable.toUpperCase);
this.AddSortType('date', SortableTable.toDate);
this.AddSortType('string');
this.AddSortType('us', usNumberConverter);
this.AddSortType('eu', euNumberConverter);
this.AddSortType('dmydate', dmyDateConverter);
this.AddSortType('ymddate', ymdDateConverter);
this.AddSortType('mdydate', mdyDateConverter);
this.AddSortType('ddmmmyyyydate', ddmmmyyyyDateConverter);
this.AddSortType('ipaddress', ipAddress, sortIP);
this.st = new SortableTable(this.tbl,sortTypes);
/*** external table headers adapter ***/
if(this.sortConfig.asyncSort && this.sortConfig.triggerIds!=null){
var triggers = this.sortConfig.triggerIds;
for(var j=0; j<triggers.length; j++){
if(triggers[j]==null) continue;
var trigger = tf_Id(triggers[j]);
if(trigger){
trigger.style.cursor = 'pointer';
trigger.onclick = function(){
if(o.sort)
o.st.asyncSort( triggers.tf_IndexByValue(this.id, true) );
}
trigger.setAttribute( '_sortType', sortTypes[j] );
}
}
}
/*** ***/
//Column sort at start
if(this.sortConfig.sortCol)
this.st.sort( this.sortConfig.sortCol[0], this.sortConfig.sortCol[1] );
this.isSortEnabled = true; //sort is set
if(this.onSortLoaded) this.onSortLoaded.call(null, this, this.st);
/*** Sort events ***/
this.st.onbeforesort = function(){
if(o.onBeforeSort) o.onBeforeSort.call(null, o, o.st.sortColumn);
o.Sort(); //TF method
/*** sort behaviour for paging ***/
if(o.paging){
isTFPaged = true;
o.paging = false;
o.RemovePaging();
}
}//onbeforesort
this.st.onsort = function(){
o.sorted = true;//table is sorted
//rows alternating bg issue
if(o.alternateBgs){
var rows = o.tbl.rows, c = 0;
function setClass(row, i, removeOnly){
if(removeOnly == undefined) removeOnly = false;
tf_removeClass(row, o.rowBgEvenCssClass);
tf_removeClass(row, o.rowBgOddCssClass);
if(!removeOnly)
tf_addClass(row, i % 2 ? o.rowBgOddCssClass : o.rowBgEvenCssClass);
}
for (var i = o.refRow; i < o.nbRows; i++) {
var isRowValid = rows[i].getAttribute('validRow');
if(o.paging && rows[i].style.display == ''){
setClass(rows[i], c);
c++;
} else {
if((isRowValid=='true' || isRowValid==null) && rows[i].style.display == ''){
setClass(rows[i], c);
c++;
} else setClass(rows[i], c, true);
}
}
}
//sort behaviour for paging
if(isTFPaged){
if(o.hasResultsPerPage)
o.fObj.paging_length = o.resultsPerPageSlc.options[o.resultsPerPageSlc.selectedIndex].value;
o.AddPaging(false);
o.SetPage(o.currentPageNb);
isTFPaged = false;
}
if(o.onAfterSort) o.onAfterSort.call(null,o,o.st.sortColumn);
}//onsort
}
//Converter fns
function usNumberConverter(s){ return tf_removeNbFormat(s,'us'); }
function euNumberConverter(s){ return tf_removeNbFormat(s,'eu'); }
function dateConverter(s, format){ return tf_formatDate(s, format); }
function dmyDateConverter(s){ return dateConverter(s,'DMY'); }
function mdyDateConverter(s){ return dateConverter(s,'MDY'); }
function ymdDateConverter(s){ return dateConverter(s,'YMD'); }
function ddmmmyyyyDateConverter(s){ return dateConverter(s,'DDMMMYYYY'); }
function ipAddress(val){
var vals = val.split('.');
for (x in vals) {
val = vals[x];
while (3 > val.length) val = '0'+val;
vals[x] = val;
}
val = vals.join('.');
return val;
}
function sortIP(a,b){
var aa = ipAddress(a.value.tf_LCase());
var bb = ipAddress(b.value.tf_LCase());
if (aa==bb) return 0;
else if (aa<bb) return -1;
else return 1;
}

View file

@ -106,11 +106,6 @@ function TableFilter(id) {
/*** Grid layout ***/
//enables/disables grid layout (fixed headers)
this.gridLayout = f.grid_layout ? true : false;
//flag indicating if the grid has an additional row for column
//widths (IE<=7)
this.hasGridWidthsRow = false;
this.gridColElms = [];
this.sourceTblHtml = null;
if(this.gridLayout){
//Firefox does not support outerHTML property...
@ -949,10 +944,6 @@ TableFilter.prototype = {
if(this.hasThemes){ this._LoadThemes(); }
if(this.gridLayout){
// this.isExternalFlt = true;
//this.SetGridLayout();
//Once grid generated 1st filterable row is 0 again
//this.refRow = hlp.isIE() ? (this.refRow+1) : 0;
var GridLayout = require('modules/gridLayout').GridLayout;
this.Cpt.gridLayout = new GridLayout(this);
this.Cpt.gridLayout.init();
@ -1591,7 +1582,6 @@ TableFilter.prototype = {
this.tbl.deleteRow(this.filtersRowIndex);
}
if(this.gridLayout){
// this.RemoveGridLayout();
this.Cpt.gridLayout.destroy();
}
dom.removeClass(this.tbl, this.prfxTf);
@ -3837,368 +3827,6 @@ TableFilter.prototype = {
}
},
/*====================================================
- generates a grid with fixed headers
=====================================================*/
// SetGridLayout: function(){
// if(!this.gridLayout){
// return;
// }
// var f = this.fObj;
// //defines grid width
// this.gridWidth = f.grid_width || null;
// //defines grid height
// this.gridHeight = f.grid_height || null;
// //defines css class for main container
// this.gridMainContCssClass = f.grid_cont_css_class || 'grd_Cont';
// //defines css class for div containing table
// this.gridContCssClass = f.grid_tbl_cont_css_class || 'grd_tblCont';
// //defines css class for div containing headers' table
// this.gridHeadContCssClass = f.grid_tblHead_cont_css_class ||
// 'grd_headTblCont';
// //defines css class for div containing rows counter, paging etc.
// this.gridInfDivCssClass = f.grid_inf_grid_css_class || 'grd_inf';
// //defines which row contains column headers
// this.gridHeadRowIndex = f.grid_headers_row_index || 0;
// //array of headers row indexes to be placed in header table
// this.gridHeadRows = f.grid_headers_rows || [0];
// //generate filters in table headers
// this.gridEnableFilters = f.grid_enable_default_filters!==undefined ?
// f.grid_enable_default_filters : true;
// //default col width
// this.gridDefaultColWidth = f.grid_default_col_width || '100px';
// //enables/disables columns resizer
// this.gridEnableColResizer = f.grid_enable_cols_resizer!==undefined ?
// f.grid_enable_cols_resizer : true;
// //defines col resizer script path
// this.gridColResizerPath = f.grid_cont_col_resizer_path ||
// this.basePath+'TFExt_ColsResizer/TFExt_ColsResizer.js';
// // in case column widths are not set default width 100px
// if(!this.hasColWidth){
// this.colWidth = [];
// for(var k=0; k<this.nbCells; k++){
// var colW,
// cell = this.tbl.rows[this.gridHeadRowIndex].cells[k];
// if(cell.width!==''){
// colW = cell.width;
// } else if(cell.style.width!==''){
// colW = parseInt(cell.style.width, 10);
// } else {
// colW = this.gridDefaultColWidth;
// }
// this.colWidth[k] = colW;
// }
// this.hasColWidth = true;
// }
// this.SetColWidths(this.gridHeadRowIndex);
// var tblW;//initial table width
// if(this.tbl.width!==''){
// tblW = this.tbl.width;
// }
// else if(this.tbl.style.width!==''){
// tblW = parseInt(this.tbl.style.width, 10);
// } else {
// tblW = this.tbl.clientWidth;
// }
// //Main container: it will contain all the elements
// this.tblMainCont = dom.create(
// 'div',['id', this.prfxMainTblCont + this.id]);
// this.tblMainCont.className = this.gridMainContCssClass;
// if(this.gridWidth){
// this.tblMainCont.style.width = this.gridWidth;
// }
// this.tbl.parentNode.insertBefore(this.tblMainCont, this.tbl);
// //Table container: div wrapping content table
// this.tblCont = dom.create('div',['id', this.prfxTblCont + this.id]);
// this.tblCont.className = this.gridContCssClass;
// if(this.gridWidth){
// this.tblCont.style.width = this.gridWidth;
// }
// if(this.gridHeight){
// this.tblCont.style.height = this.gridHeight;
// }
// this.tbl.parentNode.insertBefore(this.tblCont, this.tbl);
// var t = this.tbl.parentNode.removeChild(this.tbl);
// this.tblCont.appendChild(t);
// //In case table width is expressed in %
// if(this.tbl.style.width === ''){
// this.tbl.style.width = (this.__containsStr('%', tblW) ?
// this.tbl.clientWidth : tblW) + 'px';
// }
// var d = this.tblCont.parentNode.removeChild(this.tblCont);
// this.tblMainCont.appendChild(d);
// //Headers table container: div wrapping headers table
// this.headTblCont = dom.create(
// 'div',['id', this.prfxHeadTblCont + this.id]);
// this.headTblCont.className = this.gridHeadContCssClass;
// if(this.gridWidth){
// this.headTblCont.style.width = this.gridWidth;
// }
// //Headers table
// this.headTbl = dom.create('table',['id', this.prfxHeadTbl + this.id]);
// var tH = dom.create('tHead'); //IE<7 needs it
// //1st row should be headers row, ids are added if not set
// //Those ids are used by the sort feature
// var hRow = this.tbl.rows[this.gridHeadRowIndex];
// var sortTriggers = [];
// for(var n=0; n<this.nbCells; n++){
// var c = hRow.cells[n];
// var thId = c.getAttribute('id');
// if(!thId || thId===''){
// thId = this.prfxGridTh+n+'_'+this.id;
// c.setAttribute('id', thId);
// }
// sortTriggers.push(thId);
// }
// //Filters row is created
// var filtersRow = dom.create('tr');
// if(this.gridEnableFilters && this.fltGrid){
// this.externalFltTgtIds = [];
// for(var j=0; j<this.nbCells; j++){
// var fltTdId = this.prfxFlt+j+ this.prfxGridFltTd +this.id;
// var cl = dom.create(this.fltCellTag, ['id', fltTdId]);
// filtersRow.appendChild(cl);
// this.externalFltTgtIds[j] = fltTdId;
// }
// }
// //Headers row are moved from content table to headers table
// for(var i=0; i<this.gridHeadRows.length; i++){
// var headRow = this.tbl.rows[this.gridHeadRows[0]];
// tH.appendChild(headRow);
// }
// this.headTbl.appendChild(tH);
// if(this.filtersRowIndex === 0){
// tH.insertBefore(filtersRow,hRow);
// } else {
// tH.appendChild(filtersRow);
// }
// this.headTblCont.appendChild(this.headTbl);
// this.tblCont.parentNode.insertBefore(this.headTblCont, this.tblCont);
// //THead needs to be removed in content table for sort feature
// var thead = dom.tag(this.tbl,'thead');
// if(thead.length>0){
// this.tbl.removeChild(thead[0]);
// }
// //Headers table style
// this.headTbl.style.width = this.tbl.style.width;
// this.headTbl.style.tableLayout = 'fixed';
// this.tbl.style.tableLayout = 'fixed';
// this.headTbl.cellPadding = this.tbl.cellPadding;
// this.headTbl.cellSpacing = this.tbl.cellSpacing;
// //Headers container width
// this.headTblCont.style.width = this.tblCont.clientWidth+'px';
// //content table without headers needs col widths to be reset
// this.SetColWidths();
// this.tbl.style.width = '';
// if(hlp.isIE()){
// this.headTbl.style.width = '';
// }
// //scroll synchronisation
// var o = this; //TF object
// this.tblCont.onscroll = function(){
// o.headTblCont.scrollLeft = this.scrollLeft;
// var _o = this; //this = scroll element
// //New pointerX calc taking into account scrollLeft
// if(!o.isPointerXOverwritten){
// try{
// o.Evt.pointerX = function(e){
// e = e || global.event;
// var scrollLeft = tf_StandardBody().scrollLeft +
// _o.scrollLeft;
// return (e.pageX + _o.scrollLeft) ||
// (e.clientX + scrollLeft);
// };
// o.isPointerXOverwritten = true;
// } catch(err) {
// o.isPointerXOverwritten = false;
// }
// }
// };
// //Sort is enabled if not specified in config object
// if(f.sort !== false){
// this.sort = true;
// this.sortConfig.asyncSort = true;
// this.sortConfig.triggerIds = sortTriggers;
// }
// if(this.gridEnableColResizer){
// if(!this.hasExtensions){
// this.extensions = {
// name:['ColumnsResizer_'+this.id],
// src:[this.gridColResizerPath],
// description:['Columns Resizing'],
// initialize:[function(o){
// o.SetColsResizer('ColumnsResizer_'+o.id);}]
// };
// this.hasExtensions = true;
// } else {
// if(!this.__containsStr(
// 'colsresizer',
// str.lower(this.extensions.src.toString())) ){
// this.extensions.name.push('ColumnsResizer_'+this.id);
// this.extensions.src.push(this.gridColResizerPath);
// this.extensions.description.push('Columns Resizing');
// this.extensions.initialize.push(function(o){
// o.SetColsResizer('ColumnsResizer_'+o.id);});
// }
// }
// }
// //Default columns resizer properties for grid layout
// f.col_resizer_cols_headers_table = this.headTbl.getAttribute('id');
// f.col_resizer_cols_headers_index = this.gridHeadRowIndex;
// f.col_resizer_width_adjustment = 0;
// f.col_enable_text_ellipsis = false;
// //Cols generation for all browsers excepted IE<=7
// o.tblHasColTag = dom.tag(o.tbl,'col').length > 0 ? true : false;
// if(!hlp.isIE()){
// //Col elements are enough to keep column widths after sorting and
// //filtering
// var createColTags = function(o){
// if(!o){
// return;
// }
// for(var k=(o.nbCells-1); k>=0; k--){
// var col = dom.create( 'col', ['id', o.id+'_col_'+k]);
// o.tbl.firstChild.parentNode.insertBefore(
// col,o.tbl.firstChild);
// col.style.width = o.colWidth[k];
// o.gridColElms[k] = col;
// }
// o.tblHasColTag = true;
// };
// if(!o.tblHasColTag){
// createColTags(o);
// } else {
// var cols = dom.tag(o.tbl,'col');
// for(var ii=0; ii<o.nbCells; ii++){
// cols[ii].setAttribute('id', o.id+'_col_'+ii);
// cols[ii].style.width = o.colWidth[ii];
// o.gridColElms.push(cols[ii]);
// }
// }
// }
// //IE <= 7 needs an additional row for widths as col element width is
// //not enough...
// if(hlp.isIE()){
// var tbody = dom.tag(o.tbl,'tbody'),
// r;
// if( tbody.length>0 ){
// r = tbody[0].insertRow(0);
// } else{
// r = o.tbl.insertRow(0);
// }
// r.style.height = '0px';
// for(var x=0; x<o.nbCells; x++){
// var col = dom.create('td', ['id', o.id+'_col_'+x]);
// col.style.width = o.colWidth[x];
// o.tbl.rows[1].cells[x].style.width = '';
// r.appendChild(col);
// o.gridColElms.push(col);
// }
// this.hasGridWidthsRow = true;
// //Data table row with widths expressed
// o.leadColWidthsRow = o.tbl.rows[0];
// o.leadColWidthsRow.setAttribute('validRow','false');
// var beforeSortFn = types.isFn(f.on_before_sort) ?
// f.on_before_sort : null;
// f.on_before_sort = function(o,colIndex){
// o.leadColWidthsRow.setAttribute('validRow','false');
// if(beforeSortFn){
// beforeSortFn.call(null,o,colIndex);
// }
// };
// var afterSortFn = types.isFn(f.on_after_sort) ?
// f.on_after_sort : null;
// f.on_after_sort = function(o,colIndex){
// if(o.leadColWidthsRow.rowIndex !== 0){
// var r = o.leadColWidthsRow;
// if(tbody.length>0){
// tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
// } else {
// o.tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
// }
// }
// if(afterSortFn){
// afterSortFn.call(null,o,colIndex);
// }
// };
// }
// var afterColResizedFn = types.isFn(f.on_after_col_resized) ?
// f.on_after_col_resized : null;
// f.on_after_col_resized = function(o,colIndex){
// if(!colIndex){
// return;
// }
// var w = o.crWColsRow.cells[colIndex].style.width;
// var col = o.gridColElms[colIndex];
// col.style.width = w;
// var thCW = o.crWColsRow.cells[colIndex].clientWidth;
// var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
// if(hlp.isIE()){
// o.tbl.style.width = o.headTbl.clientWidth+'px';
// }
// if(thCW != tdCW && !hlp.isIE()){
// o.headTbl.style.width = o.tbl.clientWidth+'px';
// }
// if(afterColResizedFn){
// afterColResizedFn.call(null,o,colIndex);
// }
// };
// if(this.tbl.clientWidth !== this.headTbl.clientWidth){
// this.tbl.style.width = this.headTbl.clientWidth+'px';
// }
// },
/*====================================================
- removes the grid layout
=====================================================*/
// RemoveGridLayout: function(){
// if(!this.gridLayout){
// return;
// }
// var t = this.tbl.parentNode.removeChild(this.tbl);
// this.tblMainCont.parentNode.insertBefore(t, this.tblMainCont);
// this.tblMainCont.parentNode.removeChild( this.tblMainCont );
// this.tblMainCont = null;
// this.headTblCont = null;
// this.headTbl = null;
// this.tblCont = null;
// this.tbl.outerHTML = this.sourceTblHtml;
// this.tbl = dom.id(this.id); //needed to keep reference
// },
/*====================================================
- generates popup filters div
=====================================================*/

View file

@ -7,10 +7,10 @@ define(["exports"], function (exports) {
var Event = {
add: function (obj, type, func, capture) {
if (obj.attachEvent) {
if (obj.addEventListener) {
obj.addEventListener(type, func, capture);
} else if (obj.attachEvent) {
obj.attachEvent("on" + type, func);
} else if (obj.addEventListener) {
obj.addEventListener(type, func, (capture === undefined ? false : capture));
} else {
obj["on" + type] = func;
}
@ -19,7 +19,7 @@ define(["exports"], function (exports) {
if (obj.detachEvent) {
obj.detachEvent("on" + type, func);
} else if (obj.removeEventListener) {
obj.removeEventListener(type, func, (capture === undefined ? false : capture));
obj.removeEventListener(type, func, capture);
} else {
obj["on" + type] = null;
}

View file

@ -1 +1 @@
{"version":3,"sources":["src-es6/event.js"],"names":[],"mappings":";;;;;;;AAIA,MAAI,KAAK,GAAG;AACR,OAAG,EAAE,UAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC;AACnC,UAAG,GAAG,CAAC,WAAW,EAAC;AACf,WAAG,CAAC,WAAW,CAAC,IAAI,GAAC,IAAI,EAAE,IAAI,CAAC,CAAC;OACpC,MACI,IAAG,GAAG,CAAC,gBAAgB,EAAC;AACzB,WAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAC3B,CAAC,OAAO,KAAG,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC;OAChD,MAAK;AACF,WAAG,CAAC,IAAI,GAAC,IAAI,CAAC,GAAG,IAAI,CAAC;OACzB;KACJ;AACD,UAAM,EAAE,UAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC;AACtC,UAAG,GAAG,CAAC,WAAW,EAAC;AACf,WAAG,CAAC,WAAW,CAAC,IAAI,GAAC,IAAI,EAAC,IAAI,CAAC,CAAC;OACnC,UACO,GAAG,CAAC,mBAAmB,EAAC;AAC5B,WAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAC9B,CAAC,OAAO,KAAG,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC;OAChD,MAAM;AACH,WAAG,CAAC,IAAI,GAAC,IAAI,CAAC,GAAG,IAAI,CAAC;OACzB;KACJ;AACD,QAAI,EAAE,UAAS,GAAG,EAAC;AACf,UAAG,CAAC,GAAG,EAAC;AACJ,WAAG,GAAG,MAAM,CAAC,KAAK,CAAC;OACtB;AACD,UAAG,GAAG,CAAC,eAAe,EAAC;AACnB,WAAG,CAAC,eAAe,EAAE,CAAC;OACzB,MAAM;AACH,WAAG,CAAC,YAAY,GAAG,IAAI,CAAC;OAC3B;KACJ;AACD,UAAM,EAAE,UAAS,GAAG,EAAC;AACjB,UAAG,CAAC,GAAG,EAAC;AACJ,WAAG,GAAG,MAAM,CAAC,KAAK,CAAC;OACtB;AACD,UAAG,GAAG,CAAC,cAAc,EAAE;AACnB,WAAG,CAAC,cAAc,EAAE,CAAC;OACxB,MAAM;AACH,WAAG,CAAC,WAAW,GAAG,KAAK,CAAC;OAC3B;KACJ;GACJ,CAAC;;AAEF,SAAO,CAAC,KAAK,GAAG,KAAK,CAAC","file":"src-es6/event.js","sourcesContent":["/**\r\n * DOM event utilities\r\n */\r\n\r\nvar Event = {\r\n add: function(obj, type, func, capture){\r\n if(obj.attachEvent){\r\n obj.attachEvent('on'+type, func);\r\n }\r\n else if(obj.addEventListener){\r\n obj.addEventListener(type, func,\r\n (capture===undefined ? false : capture));\r\n } else{\r\n obj['on'+type] = func;\r\n }\r\n },\r\n remove: function(obj, type, func, capture){\r\n if(obj.detachEvent){\r\n obj.detachEvent('on'+type,func);\r\n }\r\n else if(obj.removeEventListener){\r\n obj.removeEventListener(type, func,\r\n (capture===undefined ? false : capture));\r\n } else {\r\n obj['on'+type] = null;\r\n }\r\n },\r\n stop: function(evt){\r\n if(!evt){\r\n evt = window.event;\r\n }\r\n if(evt.stopPropagation){\r\n evt.stopPropagation();\r\n } else {\r\n evt.cancelBubble = true;\r\n }\r\n },\r\n cancel: function(evt){\r\n if(!evt){\r\n evt = window.event;\r\n }\r\n if(evt.preventDefault) {\r\n evt.preventDefault();\r\n } else {\r\n evt.returnValue = false;\r\n }\r\n }\r\n};\r\n\r\nexports.Event = Event;\r\n"]}
{"version":3,"sources":["src-es6/event.js"],"names":[],"mappings":";;;;;;;AAIA,MAAI,KAAK,GAAG;AACR,OAAG,EAAE,UAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC;AACnC,UAAG,GAAG,CAAC,gBAAgB,EAAC;AACpB,WAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;OAC7C,MACI,IAAG,GAAG,CAAC,WAAW,EAAC;AACpB,WAAG,CAAC,WAAW,CAAC,IAAI,GAAC,IAAI,EAAE,IAAI,CAAC,CAAC;OACpC,MAAM;AACH,WAAG,CAAC,IAAI,GAAC,IAAI,CAAC,GAAG,IAAI,CAAC;OACzB;KACJ;AACD,UAAM,EAAE,UAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC;AACtC,UAAG,GAAG,CAAC,WAAW,EAAC;AACf,WAAG,CAAC,WAAW,CAAC,IAAI,GAAC,IAAI,EAAC,IAAI,CAAC,CAAC;OACnC,MACI,IAAG,GAAG,CAAC,mBAAmB,EAAC;AAC5B,WAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;OAChD,MAAM;AACH,WAAG,CAAC,IAAI,GAAC,IAAI,CAAC,GAAG,IAAI,CAAC;OACzB;KACJ;AACD,QAAI,EAAE,UAAS,GAAG,EAAC;AACf,UAAG,CAAC,GAAG,EAAC;AACJ,WAAG,GAAG,MAAM,CAAC,KAAK,CAAC;OACtB;AACD,UAAG,GAAG,CAAC,eAAe,EAAC;AACnB,WAAG,CAAC,eAAe,EAAE,CAAC;OACzB,MAAM;AACH,WAAG,CAAC,YAAY,GAAG,IAAI,CAAC;OAC3B;KACJ;AACD,UAAM,EAAE,UAAS,GAAG,EAAC;AACjB,UAAG,CAAC,GAAG,EAAC;AACJ,WAAG,GAAG,MAAM,CAAC,KAAK,CAAC;OACtB;AACD,UAAG,GAAG,CAAC,cAAc,EAAE;AACnB,WAAG,CAAC,cAAc,EAAE,CAAC;OACxB,MAAM;AACH,WAAG,CAAC,WAAW,GAAG,KAAK,CAAC;OAC3B;KACJ;GACJ,CAAC;;AAEF,SAAO,CAAC,KAAK,GAAG,KAAK,CAAC","file":"src-es6/event.js","sourcesContent":["/**\r\n * DOM event utilities\r\n */\r\n\r\nvar Event = {\r\n add: function(obj, type, func, capture){\r\n if(obj.addEventListener){\r\n obj.addEventListener(type, func, capture);\r\n }\r\n else if(obj.attachEvent){\r\n obj.attachEvent('on'+type, func);\r\n } else {\r\n obj['on'+type] = func;\r\n }\r\n },\r\n remove: function(obj, type, func, capture){\r\n if(obj.detachEvent){\r\n obj.detachEvent('on'+type,func);\r\n }\r\n else if(obj.removeEventListener){\r\n obj.removeEventListener(type, func, capture);\r\n } else {\r\n obj['on'+type] = null;\r\n }\r\n },\r\n stop: function(evt){\r\n if(!evt){\r\n evt = window.event;\r\n }\r\n if(evt.stopPropagation){\r\n evt.stopPropagation();\r\n } else {\r\n evt.cancelBubble = true;\r\n }\r\n },\r\n cancel: function(evt){\r\n if(!evt){\r\n evt = window.event;\r\n }\r\n if(evt.preventDefault) {\r\n evt.preventDefault();\r\n } else {\r\n evt.returnValue = false;\r\n }\r\n }\r\n};\r\n\r\nexports.Event = Event;\r\n"]}

View file

@ -2,6 +2,7 @@
<html lang="en">
<head>
<title>HTML Table Filter Generator</title>
<link href="./filtergrid.css" rel="stylesheet" type="text/css">
<script src="../libs/requirejs/require.js"></script>
</head>
<body>
@ -12,7 +13,7 @@
<th>Destination</th>
<th>Road Distance (km)</th>
<th>By Air (hrs)</th>
<th width="15%">By Rail (hrs)</th>
<th>By Rail (hrs)</th>
</tr>
<tr>
<td><strong>Sydney</strong></td>

View file

@ -39,6 +39,8 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
//defines col resizer script path
this.gridColResizerPath = f.grid_cont_col_resizer_path || this.basePath + "TFExt_ColsResizer/TFExt_ColsResizer.js";
this.gridColElms = [];
this.tf = tf;
};
@ -50,6 +52,10 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
var f = tf.fObj;
var tbl = tf.tbl;
if (!tf.gridLayout) {
return;
}
tf.isExternalFlt = true;
// default width of 100px if column widths not set
@ -172,21 +178,21 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
this.headTbl.cellPadding = tbl.cellPadding;
this.headTbl.cellSpacing = tbl.cellSpacing;
//Headers container width
this.headTblCont.style.width = this.tblCont.clientWidth + "px";
//content table without headers needs col widths to be reset
tf.SetColWidths();
//Headers container width
this.headTblCont.style.width = this.tblCont.clientWidth + "px";
tbl.style.width = "";
if (Helpers.isIE()) {
this.headTbl.style.width = "";
}
// if(Helpers.isIE()){
// this.headTbl.style.width = '';
// }
//scroll synchronisation
var o = this; //TF object
var o = this;
Event.add(this.tblCont, "scroll", function () {
Event.add(this.tblCont, "scroll", function (evt) {
//this = scroll element
var scrollLeft = this.scrollLeft;
o.headTblCont.scrollLeft = scrollLeft;
@ -243,78 +249,82 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
//Cols generation for all browsers excepted IE<=7
o.tblHasColTag = Dom.tag(tbl, "col").length > 0 ? true : false;
if (!Helpers.isIE()) {
//Col elements are enough to keep column widths after sorting and
//filtering
var createColTags = function (o) {
if (!o) {
return;
}
for (var k = (o.nbCells - 1); k >= 0; k--) {
var col = Dom.create("col", ["id", o.id + "_col_" + k]);
tbl.firstChild.parentNode.insertBefore(col, tbl.firstChild);
col.style.width = o.colWidth[k];
o.gridColElms[k] = col;
}
o.tblHasColTag = true;
};
if (!o.tblHasColTag) {
createColTags(o);
} else {
var cols = Dom.tag(tbl, "col");
for (var ii = 0; ii < o.nbCells; ii++) {
cols[ii].setAttribute("id", o.id + "_col_" + ii);
cols[ii].style.width = o.colWidth[ii];
o.gridColElms.push(cols[ii]);
}
// if(!Helpers.isIE()){
//Col elements are enough to keep column widths after sorting and
//filtering
var createColTags = function (o) {
if (!o) {
return;
}
for (var k = (tf.nbCells - 1); k >= 0; k--) {
var col = Dom.create("col", ["id", tf.id + "_col_" + k]);
tbl.firstChild.parentNode.insertBefore(col, tbl.firstChild);
col.style.width = tf.colWidth[k];
o.gridColElms[k] = col;
}
o.tblHasColTag = true;
};
if (!o.tblHasColTag) {
createColTags(o);
} else {
var cols = Dom.tag(tbl, "col");
for (var ii = 0; ii < tf.nbCells; ii++) {
cols[ii].setAttribute("id", tf.id + "_col_" + ii);
cols[ii].style.width = tf.colWidth[ii];
o.gridColElms.push(cols[ii]);
}
}
// }
//IE <= 7 needs an additional row for widths as col element width is
//not enough...
if (Helpers.isIE()) {
var tbody = Dom.tag(tbl, "tbody"), r;
if (tbody.length > 0) {
r = tbody[0].insertRow(0);
} else {
r = tbl.insertRow(0);
}
r.style.height = "0px";
for (var x = 0; x < o.nbCells; x++) {
var col = Dom.create("td", ["id", o.id + "_col_" + x]);
col.style.width = o.colWidth[x];
tbl.rows[1].cells[x].style.width = "";
r.appendChild(col);
o.gridColElms.push(col);
}
this.hasGridWidthsRow = true;
//Data table row with widths expressed
o.leadColWidthsRow = tbl.rows[0];
o.leadColWidthsRow.setAttribute("validRow", "false");
// if(Helpers.isIE()){
// var tbody = Dom.tag(tbl,'tbody'),
// r;
// if( tbody.length>0 ){
// r = tbody[0].insertRow(0);
// } else{
// r = tbl.insertRow(0);
// }
// r.style.height = '0px';
// for(var x=0; x<o.nbCells; x++){
// var col = Dom.create('td', ['id', o.id+'_col_'+x]);
// col.style.width = o.colWidth[x];
// tbl.rows[1].cells[x].style.width = '';
// r.appendChild(col);
// o.gridColElms.push(col);
// }
// tf.hasGridWidthsRow = true;
// //Data table row with widths expressed
// o.leadColWidthsRow = tbl.rows[0];
// o.leadColWidthsRow.setAttribute('validRow', 'false');
var beforeSortFn = Types.isFn(f.on_before_sort) ? f.on_before_sort : null;
f.on_before_sort = function (o, colIndex) {
o.leadColWidthsRow.setAttribute("validRow", "false");
if (beforeSortFn) {
beforeSortFn.call(null, o, colIndex);
}
};
// var beforeSortFn = Types.isFn(f.on_before_sort) ?
// f.on_before_sort : null;
// f.on_before_sort = function(o, colIndex){
// o.leadColWidthsRow.setAttribute('validRow', 'false');
// if(beforeSortFn){
// beforeSortFn.call(null, o, colIndex);
// }
// };
var afterSortFn = Types.isFn(f.on_after_sort) ? f.on_after_sort : null;
f.on_after_sort = function (o, colIndex) {
if (o.leadColWidthsRow.rowIndex !== 0) {
var r = o.leadColWidthsRow;
if (tbody.length > 0) {
tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
} else {
tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
}
}
if (afterSortFn) {
afterSortFn.call(null, o, colIndex);
}
};
}
// var afterSortFn = Types.isFn(f.on_after_sort) ?
// f.on_after_sort : null;
// f.on_after_sort = function(o,colIndex){
// if(o.leadColWidthsRow.rowIndex !== 0){
// var r = o.leadColWidthsRow;
// if(tbody.length>0){
// tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
// } else {
// tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
// }
// }
// if(afterSortFn){
// afterSortFn.call(null, o, colIndex);
// }
// };
// }
var afterColResizedFn = Types.isFn(f.on_after_col_resized) ? f.on_after_col_resized : null;
f.on_after_col_resized = function (o, colIndex) {
@ -328,11 +338,11 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
var thCW = o.crWColsRow.cells[colIndex].clientWidth;
var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
if (Helpers.isIE()) {
tbl.style.width = o.headTbl.clientWidth + "px";
}
// if(Helpers.isIE()){
// tbl.style.width = o.headTbl.clientWidth+'px';
// }
if (thCW != tdCW && !Helpers.isIE()) {
if (thCW != tdCW /*&& !Helpers.isIE()*/) {
o.headTbl.style.width = tbl.clientWidth + "px";
}
@ -346,7 +356,7 @@ define(["exports", "../dom", "../types", "../helpers", "../event"], function (ex
}
// Re-adjust reference row
tf.refRow = Helpers.isIE() ? (tf.refRow + 1) : 0;
//tf.refRow = Helpers.isIE() ? (tf.refRow+1) : 0;
}
},
destroy: {

File diff suppressed because one or more lines are too long

438
src/sortabletable.js Normal file
View file

@ -0,0 +1,438 @@
/*----------------------------------------------------------------------------\
| Sortable Table 1.12 |
|-----------------------------------------------------------------------------|
| Created by Erik Arvidsson |
| (http://webfx.eae.net/contact.html#erik) |
| For WebFX (http://webfx.eae.net/) |
|-----------------------------------------------------------------------------|
| A DOM 1 based script that allows an ordinary HTML table to be sortable. |
|-----------------------------------------------------------------------------|
| Copyright (c) 1998 - 2006 Erik Arvidsson |
|-----------------------------------------------------------------------------|
| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| use this file except in compliance with the License. You may obtain a copy |
| of the License at http://www.apache.org/licenses/LICENSE-2.0 |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| License for the specific language governing permissions and limitations |
| under the License. |
|-----------------------------------------------------------------------------|
| 2003-01-10 | First version |
| 2003-01-19 | Minor changes to the date parsing |
| 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator) |
| 2003-02-01 | Sloppy typo like error fixed in getInnerText |
| 2003-07-04 | Added workaround for IE cellIndex bug. |
| 2003-11-09 | The bDescending argument to sort was not correctly working |
| | Using onclick DOM0 event if no support for addEventListener |
| | or attachEvent |
| 2004-01-13 | Adding addSortType and removeSortType which makes it a lot |
| | easier to add new, custom sort types. |
| 2004-01-27 | Switch to use descending = false as the default sort order. |
| | Change defaultDescending to suit your needs. |
| 2004-03-14 | Improved sort type None look and feel a bit |
| 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you |
| | can use another tHead or no tHead, and you can chose some |
| | other tBody. |
| 2006-04-25 | Changed license to Apache Software License 2.0 |
|-----------------------------------------------------------------------------|
| Created 2003-01-10 | All changes are in the log above. | Updated 2006-04-25 |
\----------------------------------------------------------------------------*/
function SortableTable(oTable, oSortTypes) {
this.sortTypes = oSortTypes || [];
this.sortColumn = null;
this.descending = null;
var oThis = this;
this._headerOnclick = function (e) {
oThis.headerOnclick(e);
};
if (oTable) {
this.setTable( oTable );
this.document = oTable.ownerDocument || oTable.document;
}
else {
this.document = document;
}
// only IE needs this
var win = this.document.defaultView || this.document.parentWindow;
this._onunload = function () {
oThis.destroy();
};
if (win && typeof win.attachEvent != "undefined") {
win.attachEvent("onunload", this._onunload);
}
}
SortableTable.gecko = navigator.product == "Gecko";
SortableTable.msie = /msie/i.test(navigator.userAgent);
// Mozilla is faster when doing the DOM manipulations on
// an orphaned element. MSIE is not
SortableTable.removeBeforeSort = SortableTable.gecko;
SortableTable.prototype.onsort = function () {};
// default sort order. true -> descending, false -> ascending
SortableTable.prototype.defaultDescending = false;
// shared between all instances. This is intentional to allow external files
// to modify the prototype
SortableTable.prototype._sortTypeInfo = {};
SortableTable.prototype.setTable = function (oTable) {
if ( this.tHead )
this.uninitHeader();
this.element = oTable;
this.setTHead( oTable.tHead );
this.setTBody( oTable.tBodies[0] );
};
SortableTable.prototype.setTHead = function (oTHead) {
if (this.tHead && this.tHead != oTHead )
this.uninitHeader();
this.tHead = oTHead;
this.initHeader( this.sortTypes );
};
SortableTable.prototype.setTBody = function (oTBody) {
this.tBody = oTBody;
};
SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
if ( this.tHead )
this.uninitHeader();
this.sortTypes = oSortTypes || [];
if ( this.tHead )
this.initHeader( this.sortTypes );
};
// adds arrow containers and events
// also binds sort type to the header cells so that reordering columns does
// not break the sort types
SortableTable.prototype.initHeader = function (oSortTypes) {
if (!this.tHead) return;
var cells = this.tHead.rows[0].cells;
var doc = this.tHead.ownerDocument || this.tHead.document;
this.sortTypes = oSortTypes || [];
var l = cells.length;
var img, c;
for (var i = 0; i < l; i++) {
c = cells[i];
if (this.sortTypes[i] != null && this.sortTypes[i] != "None") {
img = doc.createElement("IMG");
img.src = "images/blank.png";
c.appendChild(img);
if (this.sortTypes[i] != null)
c._sortType = this.sortTypes[i];
if (typeof c.addEventListener != "undefined")
c.addEventListener("click", this._headerOnclick, false);
else if (typeof c.attachEvent != "undefined")
c.attachEvent("onclick", this._headerOnclick);
else
c.onclick = this._headerOnclick;
}
else
{
c.setAttribute( "_sortType", oSortTypes[i] );
c._sortType = "None";
}
}
this.updateHeaderArrows();
};
// remove arrows and events
SortableTable.prototype.uninitHeader = function () {
if (!this.tHead) return;
var cells = this.tHead.rows[0].cells;
var l = cells.length;
var c;
for (var i = 0; i < l; i++) {
c = cells[i];
if (c._sortType != null && c._sortType != "None") {
c.removeChild(c.lastChild);
if (typeof c.removeEventListener != "undefined")
c.removeEventListener("click", this._headerOnclick, false);
else if (typeof c.detachEvent != "undefined")
c.detachEvent("onclick", this._headerOnclick);
c._sortType = null;
c.removeAttribute( "_sortType" );
}
}
};
SortableTable.prototype.updateHeaderArrows = function () {
if (!this.tHead) return;
var cells = this.tHead.rows[0].cells;
var l = cells.length;
var img;
for (var i = 0; i < l; i++) {
if (cells[i]._sortType != null && cells[i]._sortType != "None") {
img = cells[i].lastChild;
if (i == this.sortColumn)
img.className = "sort-arrow " + (this.descending ? "descending" : "ascending");
else
img.className = "sort-arrow";
}
}
};
SortableTable.prototype.headerOnclick = function (e) {
// find TD element
var el = e.target || e.srcElement;
while (el.tagName != "TD")
el = el.parentNode;
this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
};
// IE returns wrong cellIndex when columns are hidden
SortableTable.getCellIndex = function (oTd) {
var cells = oTd.parentNode.childNodes
var l = cells.length;
var i;
for (i = 0; cells[i] != oTd && i < l; i++)
;
return i;
};
SortableTable.prototype.getSortType = function (nColumn) {
return this.sortTypes[nColumn] || "String";
};
// only nColumn is required
// if bDescending is left out the old value is taken into account
// if sSortType is left out the sort type is found from the sortTypes array
SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
if (!this.tBody) return;
if (sSortType == null)
sSortType = this.getSortType(nColumn);
// exit if None
if (sSortType == "None")
return;
if (bDescending == null) {
if (this.sortColumn != nColumn)
this.descending = this.defaultDescending;
else
this.descending = !this.descending;
}
else
this.descending = bDescending;
this.sortColumn = nColumn;
if (typeof this.onbeforesort == "function")
this.onbeforesort();
var f = this.getSortFunction(sSortType, nColumn);
var a = this.getCache(sSortType, nColumn);
var tBody = this.tBody;
a.sort(f);
if (this.descending)
a.reverse();
if (SortableTable.removeBeforeSort) {
// remove from doc
var nextSibling = tBody.nextSibling;
var p = tBody.parentNode;
p.removeChild(tBody);
}
// insert in the new order
var l = a.length;
for (var i = 0; i < l; i++)
tBody.appendChild(a[i].element);
if (SortableTable.removeBeforeSort) {
// insert into doc
p.insertBefore(tBody, nextSibling);
}
this.updateHeaderArrows();
this.destroyCache(a);
if (typeof this.onsort == "function")
this.onsort();
};
SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) {
var oThis = this;
this._asyncsort = function () {
oThis.sort(nColumn, bDescending, sSortType);
};
window.setTimeout(this._asyncsort, 1);
};
SortableTable.prototype.getCache = function (sType, nColumn) {
if (!this.tBody) return [];
var rows = this.tBody.rows;
var l = rows.length;
var a = new Array(l);
var r;
for (var i = 0; i < l; i++) {
r = rows[i];
a[i] = {
value: this.getRowValue(r, sType, nColumn),
element: r
};
};
return a;
};
SortableTable.prototype.destroyCache = function (oArray) {
var l = oArray.length;
for (var i = 0; i < l; i++) {
oArray[i].value = null;
oArray[i].element = null;
oArray[i] = null;
}
};
SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
// if we have defined a custom getRowValue use that
if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
var s;
var c = oRow.cells[nColumn];
if (typeof c.innerText != "undefined")
s = c.innerText;
else
s = SortableTable.getInnerText(c);
return this.getValueFromString(s, sType);
};
SortableTable.getInnerText = function (oNode) {
var s = "";
var cs = oNode.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
s += SortableTable.getInnerText(cs[i]);
break;
case 3: //TEXT_NODE
s += cs[i].nodeValue;
break;
}
}
return s;
};
SortableTable.prototype.getValueFromString = function (sText, sType) {
if (this._sortTypeInfo[sType])
return this._sortTypeInfo[sType].getValueFromString( sText );
return sText;
/*
switch (sType) {
case "Number":
return Number(sText);
case "CaseInsensitiveString":
return sText.toUpperCase();
case "Date":
var parts = sText.split("-");
var d = new Date(0);
d.setFullYear(parts[0]);
d.setDate(parts[2]);
d.setMonth(parts[1] - 1);
return d.valueOf();
}
return sText;
*/
};
SortableTable.prototype.getSortFunction = function (sType, nColumn) {
if (this._sortTypeInfo[sType])
return this._sortTypeInfo[sType].compare;
return SortableTable.basicCompare;
};
SortableTable.prototype.destroy = function () {
this.uninitHeader();
var win = this.document.parentWindow;
if (win && typeof win.detachEvent != "undefined") { // only IE needs this
win.detachEvent("onunload", this._onunload);
}
this._onunload = null;
this.element = null;
this.tHead = null;
this.tBody = null;
this.document = null;
this._headerOnclick = null;
this.sortTypes = null;
this._asyncsort = null;
this.onsort = null;
};
// Adds a sort type to all instance of SortableTable
// sType : String - the identifier of the sort type
// fGetValueFromString : function ( s : string ) : T - A function that takes a
// string and casts it to a desired format. If left out the string is just
// returned
// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
// compare function. Takes two values and compares them. If left out less than,
// <, compare is used
// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function
// that takes the row and the column index and returns the value used to compare.
// If left out then the innerText is first taken for the cell and then the
// fGetValueFromString is used to convert that string the desired value and type
SortableTable.prototype.addSortType = function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) {
this._sortTypeInfo[sType] = {
type: sType,
getValueFromString: fGetValueFromString || SortableTable.idFunction,
compare: fCompareFunction || SortableTable.basicCompare,
getRowValue: fGetRowValue
};
};
// this removes the sort type from all instances of SortableTable
SortableTable.prototype.removeSortType = function (sType) {
delete this._sortTypeInfo[sType];
};
SortableTable.basicCompare = function compare(n1, n2) {
if (n1.value < n2.value)
return -1;
if (n2.value < n1.value)
return 1;
return 0;
};
SortableTable.idFunction = function (x) {
return x;
};
SortableTable.toUpperCase = function (s) {
return s.toUpperCase();
};
SortableTable.toDate = function (s) {
var parts = s.split("-");
var d = new Date(0);
d.setFullYear(parts[0]);
d.setDate(parts[2]);
d.setMonth(parts[1] - 1);
return d.valueOf();
};
// add sort types
SortableTable.prototype.addSortType("Number", Number);
SortableTable.prototype.addSortType("CaseInsensitiveString", SortableTable.toUpperCase);
SortableTable.prototype.addSortType("Date", SortableTable.toDate);
SortableTable.prototype.addSortType("String");
// None is a special case