2015-11-16 13:21:19 +01:00
|
|
|
import {Feature} from './feature';
|
2015-05-30 14:23:33 +02:00
|
|
|
import Dom from '../dom';
|
|
|
|
import Types from '../types';
|
|
|
|
import Event from '../event';
|
2014-11-22 15:01:29 +01:00
|
|
|
|
2015-11-16 13:21:19 +01:00
|
|
|
export class GridLayout extends Feature{
|
2014-11-22 15:01:29 +01:00
|
|
|
|
2014-11-23 11:31:55 +01:00
|
|
|
/**
|
|
|
|
* Grid layout, table with fixed headers
|
|
|
|
* @param {Object} tf TableFilter instance
|
|
|
|
*/
|
2015-11-16 13:21:19 +01:00
|
|
|
constructor(tf){
|
|
|
|
super(tf, 'gridLayout');
|
|
|
|
|
|
|
|
var f = this.config;
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
//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';
|
|
|
|
|
2014-11-23 11:31:55 +01:00
|
|
|
this.gridColElms = [];
|
|
|
|
|
2015-04-06 11:53:01 +02:00
|
|
|
//div containing grid elements if grid_layout true
|
|
|
|
this.prfxMainTblCont = 'gridCont_';
|
|
|
|
//div containing table if grid_layout true
|
|
|
|
this.prfxTblCont = 'tblCont_';
|
|
|
|
//div containing headers table if grid_layout true
|
|
|
|
this.prfxHeadTblCont = 'tblHeadCont_';
|
|
|
|
//headers' table if grid_layout true
|
|
|
|
this.prfxHeadTbl = 'tblHead_';
|
|
|
|
//id of td containing the filter if grid_layout true
|
|
|
|
this.prfxGridFltTd = '_td_';
|
|
|
|
//id of th containing column header if grid_layout true
|
|
|
|
this.prfxGridTh = 'tblHeadTh_';
|
|
|
|
|
2015-10-28 08:09:37 +01:00
|
|
|
this.sourceTblHtml = tf.tbl.outerHTML;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
|
|
|
|
2014-11-23 11:31:55 +01:00
|
|
|
/**
|
|
|
|
* Generates a grid with fixed headers
|
|
|
|
*/
|
2014-11-22 15:01:29 +01:00
|
|
|
init(){
|
|
|
|
var tf = this.tf;
|
2015-11-16 13:21:19 +01:00
|
|
|
var f = this.config;
|
2014-11-22 15:01:29 +01:00
|
|
|
var tbl = tf.tbl;
|
|
|
|
|
2015-11-16 13:21:19 +01:00
|
|
|
if(this.initialized){
|
2014-11-23 11:31:55 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-22 15:01:29 +01:00
|
|
|
tf.isExternalFlt = true;
|
|
|
|
|
2014-11-23 04:34:57 +01:00
|
|
|
// default width of 100px if column widths not set
|
2015-05-28 15:44:23 +02:00
|
|
|
if(!tf.hasColWidths){
|
|
|
|
tf.colWidths = [];
|
2014-11-22 15:01:29 +01:00
|
|
|
for(var k=0; k<tf.nbCells; k++){
|
|
|
|
var colW,
|
|
|
|
cell = tbl.rows[this.gridHeadRowIndex].cells[k];
|
2014-11-23 04:34:57 +01:00
|
|
|
if(cell.width !== ''){
|
2014-11-22 15:01:29 +01:00
|
|
|
colW = cell.width;
|
2014-11-23 04:34:57 +01:00
|
|
|
} else if(cell.style.width !== ''){
|
2014-11-22 15:01:29 +01:00
|
|
|
colW = parseInt(cell.style.width, 10);
|
|
|
|
} else {
|
|
|
|
colW = this.gridDefaultColWidth;
|
|
|
|
}
|
2015-05-28 15:44:23 +02:00
|
|
|
tf.colWidths[k] = colW;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
2015-05-28 15:44:23 +02:00
|
|
|
tf.hasColWidths = true;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
2015-02-21 04:39:09 +01:00
|
|
|
tf.setColWidths(this.gridHeadRowIndex);
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
var tblW;//initial table width
|
2014-11-23 04:34:57 +01:00
|
|
|
if(tbl.width !== ''){
|
2014-11-22 15:01:29 +01:00
|
|
|
tblW = tbl.width;
|
|
|
|
}
|
2014-11-23 04:34:57 +01:00
|
|
|
else if(tbl.style.width !== ''){
|
2014-11-22 15:01:29 +01:00
|
|
|
tblW = parseInt(tbl.style.width, 10);
|
|
|
|
} else {
|
|
|
|
tblW = tbl.clientWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Main container: it will contain all the elements
|
2015-04-06 11:53:01 +02:00
|
|
|
this.tblMainCont = Dom.create('div',
|
|
|
|
['id', this.prfxMainTblCont + tf.id]);
|
2014-11-22 15:01:29 +01:00
|
|
|
this.tblMainCont.className = this.gridMainContCssClass;
|
|
|
|
if(this.gridWidth){
|
|
|
|
this.tblMainCont.style.width = this.gridWidth;
|
|
|
|
}
|
2014-11-23 04:34:57 +01:00
|
|
|
tbl.parentNode.insertBefore(this.tblMainCont, tbl);
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
//Table container: div wrapping content table
|
2015-04-06 11:53:01 +02:00
|
|
|
this.tblCont = Dom.create('div',['id', this.prfxTblCont + tf.id]);
|
2014-11-22 15:01:29 +01:00
|
|
|
this.tblCont.className = this.gridContCssClass;
|
|
|
|
if(this.gridWidth){
|
2015-06-13 13:23:33 +02:00
|
|
|
if(this.gridWidth.indexOf('%') != -1){
|
|
|
|
console.log(this.gridWidth);
|
|
|
|
this.tblCont.style.width = '100%';
|
|
|
|
} else {
|
|
|
|
this.tblCont.style.width = this.gridWidth;
|
|
|
|
}
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
|
|
|
if(this.gridHeight){
|
|
|
|
this.tblCont.style.height = this.gridHeight;
|
|
|
|
}
|
2014-11-23 04:34:57 +01:00
|
|
|
tbl.parentNode.insertBefore(this.tblCont, tbl);
|
|
|
|
var t = tbl.parentNode.removeChild(tbl);
|
2014-11-22 15:01:29 +01:00
|
|
|
this.tblCont.appendChild(t);
|
|
|
|
|
|
|
|
//In case table width is expressed in %
|
|
|
|
if(tbl.style.width === ''){
|
2015-02-21 04:39:09 +01:00
|
|
|
tbl.style.width = (tf._containsStr('%', tblW) ?
|
2014-11-22 15:01:29 +01:00
|
|
|
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(
|
2015-04-06 11:53:01 +02:00
|
|
|
'div',['id', this.prfxHeadTblCont + tf.id]);
|
2014-11-22 15:01:29 +01:00
|
|
|
this.headTblCont.className = this.gridHeadContCssClass;
|
|
|
|
if(this.gridWidth){
|
2015-06-13 13:23:33 +02:00
|
|
|
if(this.gridWidth.indexOf('%') != -1){
|
|
|
|
console.log(this.gridWidth);
|
|
|
|
this.headTblCont.style.width = '100%';
|
|
|
|
} else {
|
|
|
|
this.headTblCont.style.width = this.gridWidth;
|
|
|
|
}
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//Headers table
|
2015-04-06 11:53:01 +02:00
|
|
|
this.headTbl = Dom.create('table', ['id', this.prfxHeadTbl + tf.id]);
|
2015-11-16 13:21:19 +01:00
|
|
|
var tH = Dom.create('tHead');
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
//1st row should be headers row, ids are added if not set
|
|
|
|
//Those ids are used by the sort feature
|
|
|
|
var hRow = tbl.rows[this.gridHeadRowIndex];
|
|
|
|
var sortTriggers = [];
|
|
|
|
for(var n=0; n<tf.nbCells; n++){
|
|
|
|
var c = hRow.cells[n];
|
|
|
|
var thId = c.getAttribute('id');
|
|
|
|
if(!thId || thId===''){
|
2015-04-06 11:53:01 +02:00
|
|
|
thId = this.prfxGridTh+n+'_'+tf.id;
|
2014-11-22 15:01:29 +01:00
|
|
|
c.setAttribute('id', thId);
|
|
|
|
}
|
|
|
|
sortTriggers.push(thId);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Filters row is created
|
|
|
|
var filtersRow = Dom.create('tr');
|
|
|
|
if(this.gridEnableFilters && tf.fltGrid){
|
|
|
|
tf.externalFltTgtIds = [];
|
|
|
|
for(var j=0; j<tf.nbCells; j++){
|
2015-04-06 11:53:01 +02:00
|
|
|
var fltTdId = tf.prfxFlt+j+ this.prfxGridFltTd +tf.id;
|
2014-11-22 15:01:29 +01:00
|
|
|
var cl = Dom.create(tf.fltCellTag, ['id', fltTdId]);
|
|
|
|
filtersRow.appendChild(cl);
|
|
|
|
tf.externalFltTgtIds[j] = fltTdId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//Headers row are moved from content table to headers table
|
|
|
|
for(var i=0; i<this.gridHeadRows.length; i++){
|
|
|
|
var headRow = tbl.rows[this.gridHeadRows[0]];
|
|
|
|
tH.appendChild(headRow);
|
|
|
|
}
|
|
|
|
this.headTbl.appendChild(tH);
|
|
|
|
if(tf.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
|
2014-11-23 04:34:57 +01:00
|
|
|
var thead = Dom.tag(tbl, 'thead');
|
2014-11-22 15:01:29 +01:00
|
|
|
if(thead.length>0){
|
|
|
|
tbl.removeChild(thead[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Headers table style
|
|
|
|
this.headTbl.style.tableLayout = 'fixed';
|
|
|
|
tbl.style.tableLayout = 'fixed';
|
|
|
|
this.headTbl.cellPadding = tbl.cellPadding;
|
|
|
|
this.headTbl.cellSpacing = tbl.cellSpacing;
|
2015-04-24 12:38:20 +02:00
|
|
|
// this.headTbl.style.width = tbl.style.width;
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
//content table without headers needs col widths to be reset
|
2015-06-06 12:06:15 +02:00
|
|
|
tf.setColWidths(0, this.headTbl);
|
2014-11-22 15:01:29 +01:00
|
|
|
|
2014-11-23 11:31:55 +01:00
|
|
|
//Headers container width
|
2015-06-13 13:23:33 +02:00
|
|
|
// this.headTblCont.style.width = this.tblCont.clientWidth+'px';
|
2014-11-23 11:31:55 +01:00
|
|
|
|
2014-11-22 15:01:29 +01:00
|
|
|
tbl.style.width = '';
|
2015-04-24 12:38:20 +02:00
|
|
|
//
|
|
|
|
this.headTbl.style.width = tbl.clientWidth + 'px';
|
|
|
|
//
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
//scroll synchronisation
|
2015-04-24 12:38:20 +02:00
|
|
|
Event.add(this.tblCont, 'scroll', (evt)=> {
|
|
|
|
var elm = Event.target(evt);
|
|
|
|
var scrollLeft = elm.scrollLeft;
|
|
|
|
this.headTblCont.scrollLeft = scrollLeft;
|
2014-11-22 15:01:29 +01:00
|
|
|
//New pointerX calc taking into account scrollLeft
|
2015-04-24 12:38:20 +02:00
|
|
|
// if(!o.isPointerXOverwritten){
|
|
|
|
// try{
|
|
|
|
// o.Evt.pointerX = function(evt){
|
|
|
|
// var e = evt || global.event;
|
|
|
|
// var bdScrollLeft = tf_StandardBody().scrollLeft +
|
|
|
|
// scrollLeft;
|
|
|
|
// return (e.pageX + scrollLeft) ||
|
|
|
|
// (e.clientX + bdScrollLeft);
|
|
|
|
// };
|
|
|
|
// o.isPointerXOverwritten = true;
|
|
|
|
// } catch(err) {
|
|
|
|
// o.isPointerXOverwritten = false;
|
|
|
|
// }
|
|
|
|
// }
|
2014-11-22 15:01:29 +01:00
|
|
|
});
|
|
|
|
|
2015-06-07 12:30:32 +02:00
|
|
|
//Configure sort extension if any
|
|
|
|
var sort = (f.extensions || []).filter(function(itm){
|
|
|
|
return itm.name === 'sort';
|
|
|
|
});
|
|
|
|
if(sort.length === 1){
|
|
|
|
sort[0].async_sort = true;
|
|
|
|
sort[0].trigger_ids = sortTriggers;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//Cols generation for all browsers excepted IE<=7
|
2015-04-24 12:38:20 +02:00
|
|
|
this.tblHasColTag = Dom.tag(tbl, 'col').length > 0 ? true : false;
|
2014-11-23 11:31:55 +01:00
|
|
|
|
2015-01-11 11:22:52 +01:00
|
|
|
//Col elements are enough to keep column widths after sorting and
|
|
|
|
//filtering
|
2015-06-06 12:06:15 +02:00
|
|
|
var createColTags = function(){
|
2015-01-11 11:22:52 +01:00
|
|
|
for(var k=(tf.nbCells-1); k>=0; k--){
|
|
|
|
var col = Dom.create('col', ['id', tf.id+'_col_'+k]);
|
2015-06-06 12:06:15 +02:00
|
|
|
tbl.insertBefore(col, tbl.firstChild);
|
2015-05-28 15:44:23 +02:00
|
|
|
col.style.width = tf.colWidths[k];
|
2015-06-06 12:06:15 +02:00
|
|
|
this.gridColElms[k] = col;
|
2015-01-11 11:22:52 +01:00
|
|
|
}
|
2015-06-06 12:06:15 +02:00
|
|
|
this.tblHasColTag = true;
|
2015-01-11 11:22:52 +01:00
|
|
|
};
|
2015-06-06 12:06:15 +02:00
|
|
|
|
2015-04-24 12:38:20 +02:00
|
|
|
if(!this.tblHasColTag){
|
2015-06-06 12:06:15 +02:00
|
|
|
createColTags.call(this);
|
2015-01-11 11:22:52 +01:00
|
|
|
} else {
|
|
|
|
var cols = Dom.tag(tbl, 'col');
|
|
|
|
for(var ii=0; ii<tf.nbCells; ii++){
|
|
|
|
cols[ii].setAttribute('id', tf.id+'_col_'+ii);
|
2015-05-28 15:44:23 +02:00
|
|
|
cols[ii].style.width = tf.colWidths[ii];
|
2015-06-06 12:06:15 +02:00
|
|
|
this.gridColElms.push(cols[ii]);
|
2015-01-11 11:22:52 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-22 15:01:29 +01:00
|
|
|
|
|
|
|
var afterColResizedFn = Types.isFn(f.on_after_col_resized) ?
|
|
|
|
f.on_after_col_resized : null;
|
2015-04-24 12:38:20 +02:00
|
|
|
f.on_after_col_resized = function(o, colIndex){
|
2014-11-22 15:01:29 +01:00
|
|
|
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;
|
|
|
|
|
2015-06-13 13:23:33 +02:00
|
|
|
if(thCW != tdCW){
|
2014-11-22 15:01:29 +01:00
|
|
|
o.headTbl.style.width = tbl.clientWidth+'px';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(afterColResizedFn){
|
|
|
|
afterColResizedFn.call(null,o,colIndex);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-11-21 04:41:40 +01:00
|
|
|
if(tf.popupFilters){
|
2015-10-11 02:36:28 +02:00
|
|
|
filtersRow.style.display = 'none';
|
|
|
|
}
|
|
|
|
|
2014-11-22 15:01:29 +01:00
|
|
|
if(tbl.clientWidth !== this.headTbl.clientWidth){
|
|
|
|
tbl.style.width = this.headTbl.clientWidth+'px';
|
|
|
|
}
|
2015-11-16 13:21:19 +01:00
|
|
|
|
|
|
|
this.initialized = true;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
|
|
|
|
2014-11-23 11:31:55 +01:00
|
|
|
/**
|
|
|
|
* Removes the grid layout
|
|
|
|
*/
|
2014-11-22 15:01:29 +01:00
|
|
|
destroy(){
|
|
|
|
var tf = this.tf;
|
|
|
|
var tbl = tf.tbl;
|
|
|
|
|
2015-11-16 13:21:19 +01:00
|
|
|
if(!this.initialized){
|
2014-11-22 15:01:29 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
var t = tbl.parentNode.removeChild(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;
|
|
|
|
|
2015-10-28 08:09:37 +01:00
|
|
|
tbl.outerHTML = this.sourceTblHtml;
|
2014-11-23 04:34:57 +01:00
|
|
|
//needed to keep reference of table element
|
2015-11-16 13:21:19 +01:00
|
|
|
this.tf.tbl = Dom.id(tf.id); // ???
|
|
|
|
|
|
|
|
this.initialized = false;
|
2014-11-22 15:01:29 +01:00
|
|
|
}
|
2015-11-16 13:21:19 +01:00
|
|
|
}
|