[Extjs]创建FormTableLayout布局器

原创,转载请标明出处。
Extjs自带的FormLayout布局若要使用多列,需要自己做tpl或者使用HTML+renderTo,很麻烦。而TableLyout只支持Flow排列,且用于FormPanel中不能正确显示Label,等等,两者皆不适合自由的table+form布局需求。 FormTablLayout解决该问题。
 
My.layout.FormTableLayout = FormLayout + TableLayout
 
增强项:可指定显示位置 …. .
使用方法:适用于 FormLayout/TableLayout 所适用场合,指定 layout formtable 即可。
 
1) 基本功能:
a)        指定表格列数 ( 行数将根据内容自动添加 )
b)        横、纵向融合
c)        一个单元格内容
d)        在一个单元格中显示多项内容
e)        指定显示位置
f)          支持显示 form field
g)        单元格内容显示模板可设置
2) 使用范例
    var items=[
    {
       html:' 横向融合 ',
       row:3,
       col:0,
       colspan:2  
    },{
       html:' ------- 我的地盘 -------- ',
       row:2,
       col:1     
    },{
       html:'======== 我也来 ===========',
       row:2,
       col:1      
}……
 
    var tableForm=new Ext.FormPanel({
       layout: 'formtable' , // 使用 FormTableLayout
       style: 'height:100%',
       title: 'Table Form',
       items: items
    });
 
3) 效果
/* *
 * @class My.ui.FormTableLayout
 * @extends Ext.layout.ContainerLayout
 * @author zfzheng
 * 
 * 
 * 
 * FormTableLayout= FormLayout + TableLayout
 * 
 * 适用于FormLayout/TableLayout适用的场合。
 * 除拥有FormLayout/TableLayout特征外,还具有指定单元格显示功能:
 *   设置autoFlow为true,根据items项的row/col属性定位单元格排列。
 *   可以在同一单元格内显示多项item(指定row/col)为同一位置即可,按在原数组中的顺序排列。
 *   注:
 *    1)若autoFlow为true,items项没有row或col属性的均不被显示。
 *    2)若某item的row/col设置在被融合了的单元格位置,则该项不被显示。
 * 
  var items=[
 {
  html:'横向融合',
  row:3,
  col:0,
  colspan:2 
 },{
  html:'-------我的地盘--------',
  row:2,
  col:1  
 },{
  html:'========我也来===========',
  row:2,
  col:1  
 },{
  html:'~~~~~~~~~真挤啊~~~~~~~~~~',
  row:2,
  col:1
 },{
  html:'非第一单元格起填充',
  row:0,
  col:1  
 },{
  html:'纵向融合',
  row:1,
  col:0,
  rowspan:2 
 },{
  html:'Hello,how are you?正常Cell',
  row:1,
  col:1  
 },{
  name:'count',
  fieldLabel:'件数',
  value:'1',
  xtype:'numberfield',
  row:4,
  col:0  
 },{
  name:'logTime',
  fieldLabel:'编制日期',
  value:'',
  xtype:'datefield',
  row:4,
  col:1  
 }  
 ]
 
 var tableForm=new Ext.FormPanel({
  layout: 'formtable', //使用FormTableLayout
  style: 'height:100%',
  title: 'Table Form',
  items: items
 });
 
 tableForm.renderTo(Ext.getBody());
 * 
 * 
 
*/
My.layout.FormTableLayout
= Ext.extend(Ext.layout.ContainerLayout,{
 
//  private
 monitorResize: false ,
 
 
/* *
  * Table列数
  
*/
 columns:
2
 
/* *
  * 是否自动排列
  *  若为true,则按行方向自动排列。
  *  若为false,则根据item指定的[row,col]排列,无row/col属性的项被忽略显示。
  
*/
 autoFlow:
false ,
 
/* *
  * Form Element显示模板
  
*/
 fieldTpl:
     
new  Ext.Template(
        
' <div class="x-form-item {5}" tabIndex="-1"> ' ,
            
' <label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label> ' ,
            
' <div class="x-form-element" id="x-form-el-{0}" style="{3}"> ' ,
            
' </div><div class="{6}"></div> ' ,
        
' </div> '
    ),
    
 
/* *
  * 普通内容(非Form Element)显示模板
  
*/     
    cellContentTpl:
new  Ext.Template( ' <div class="x-form-item-label">{0}</div> ' ),
    
    
//  private
    setContainer :  function (ct){
        My.layout.FormTableLayout.superclass.setContainer.call(
this , ct);
        
this .currentRow  =   0 ;
        
this .currentColumn  =   0 ;
        
this .spanCells  =  [];
        
this .maxCreatedRowIndex =- 1 ;
    },    
    
    
//  private
 onLayout :  function (ct, target){
     
var  cs  =  ct.items.items, len  =  cs.length;
     
if ( ! this .table){
         
// target.addClass('x-table-layout-ct');
          this .table  =  target.createChild(
             {tag:
' table ' , cls: ' x-table-layout ' , border: 1 , cellspacing: 3 , cn: {tag:  ' tbody ' }},  null true );
   
         
if ( ! this .autoFlow){
          
var  items = [];
          
for ( var  i = 0 ;i < len;i ++ ){
           
// 如果设置了autoFlow为true,则无row、col属性的字段将无法显示。
            if ( typeof  cs[i].row != ' undefined '   &&   typeof  cs[i].col != ' undefined ' ){
            cs[i].__index
= i;
      items.push(cs[i]);
           }
          }
          ct.items.items
= items.sort( function (item1,item2){
           
if (item1.row == item2.row){
            
if (item1.col == item2.col){
             
return  item1.__index - item2.__index;
            }
            
return  item1.col - item2.col;
           }
           
return  item1.row - item2.row;
          });
         }
         
this .renderAll(ct, target);
     }
 },
 
    
//  private
    createRow :  function (index){
        
var  row  =   this .table.tBodies[ 0 ].childNodes[index];
        
if ( ! row){
            row 
=  document.createElement( ' tr ' );
            
this .table.tBodies[ 0 ].appendChild(row);
            
this .maxCreatedRowIndex = Math.max( this .maxCreatedRowIndex,index);
        }
        
return  row;
    },
        
    
//  private
 getRow :  function (index){
  
if ( ! this .autoFlow){
   
// 确保创建index之前的row
    for ( var  i = Math.max( 0 , this .maxCreatedRowIndex + 1 );i < index;i ++ ){
    
this .createRow(i);
   } 
  }
  
return   this .createRow(index);
 },
 
 
//  private
 getCellAt :  function (c,row,col){
  
if ( this .spanCells[col]  &&   this .spanCells[col][row]){
   
return   null ;
  }
  
// 计算之前有多少spanCells
   var  spanCount = 0 ;  
  
for ( var  i = 0 ;i < col;i ++ ){
   
if ( this .spanCells[i]  &&   this .spanCells[i][row]){
    spanCount
++ ;
   }   
  }
  
var  r = this .getRow(row);
  
var  cell = r.childNodes[col - spanCount];
  
if (cell){
   
return  cell;
  }
  
this .currentRow = row;
  
// 预设置nextCell之前的初始列索引
   this .currentColumn = spanCount - 1 ;
  
for ( var  i = spanCount;i <= col;i ++ ){
   
this .getNextCell(c);
  }
  
return  r.childNodes[col - spanCount];
 },
 
    
//  private
 getNextCell :  function (c){
        
var  td  =  document.createElement( ' td ' ), row, colIndex;
        
if ( ! this .columns){
            row 
=   this .getRow( 0 );
        }
else  {
         colIndex 
=   this .currentColumn;
            
if (colIndex  !==   0   &&  (colIndex  %   this .columns  ===   0 )){
                
this .currentRow ++ ;
                colIndex 
=  (c.colspan  ||   1 );
            }
else {
                colIndex 
+=  (c.colspan  ||   1 );
            }
            
            
// advance to the next non-spanning row/col position
             var  cell  =   this .getNextNonSpan(colIndex,  this .currentRow);
            
this .currentColumn  =  cell[ 0 ];
            
if (cell[ 1 !=   this .currentRow){
             
this .currentRow  =  cell[ 1 ];
             
if (c.colspan){
              
this .currentColumn  +=  c.colspan  -   1 ;
             }
            }
            row 
=   this .getRow( this .currentRow);
        }
        
if (c.colspan){
            td.colSpan 
=  c.colspan;
        }
  td.className 
=   ' x-table-layout-cell ' ;
        
if (c.rowspan){
            td.rowSpan 
=  c.rowspan;
   
var  rowIndex  =   this .currentRow, colspan  =  c.colspan  ||   1 ;
   
// track rowspanned cells to add to the column index during the next call to getNextCell
    for ( var  r  =  rowIndex + 1 ; r  <  rowIndex + c.rowspan; r ++ ){
    
for ( var  col = this .currentColumn - colspan + 1 ; col  <=   this .currentColumn; col ++ ){
     
if ( ! this .spanCells[col]){
      
this .spanCells[col]  =  [];
     }
     
this .spanCells[col][r]  =   1 ;
    }
   }
        }
        row.appendChild(td);
        
return  td;
    },
    
    
//  private
    getNextNonSpan:  function (colIndex, rowIndex){
     
var  c  =  (colIndex  <=   this .columns  ?  colIndex :  this .columns), r  =  rowIndex;
        
for ( var  i = c; i  <=   this .columns; i ++ ){
         
if ( this .spanCells[i]  &&   this .spanCells[i][r]){
          
if ( ++ >   this .columns){
           
// exceeded column count, so reset to the start of the next row
                  return   this .getNextNonSpan( 1 ++ r);
          }
         }
else {
          
break ;
         }
        }
        
return  [c,r];
    },
    
 
//  private
    renderItem :  function (c, position, target){
     
// target is form or other container
      if (c  &&   ! c.rendered ){
      
var  td = this .autoFlow ? this .getNextCell(c): this .getCellAt(c,c.row,c.col);
      
if ( ! td){
       
// cell at[row,col] is spanCell,不渲染。(row,col设置不正确)
        return ;
      }
         
if (c.isFormField  &&  c.inputType  !=   ' hidden ' ){
             
var  args  =  [
                    c.id, c.fieldLabel,
                    c.labelStyle
|| this .labelStyle || '' ,
                    
this .elementStyle || '' ,
                    
typeof  c.labelSeparator  ==   ' undefined '   ?   this .labelSeparator : c.labelSeparator,
                    (c.itemCls
|| this .container.itemCls || '' +  (c.hideLabel  ?   '  x-hide-label '  :  '' ),
                    c.clearCls 
||   ' x-form-clear-left '  
             ];
             
if ( typeof  position  ==   ' number ' ){
                 position 
=  target.dom.childNodes[position]  ||   null ;
             }
             
if (position){
              
// this.fieldTpl.insertBefore(position, args);
                  this .fieldTpl.append(td, args);
             }
else {
                 
// this.fieldTpl.append(target, args);
               this .fieldTpl.append(td, args);
             }
             c.render(
' x-form-el- ' + c.id);
         }
else  {
             
// My.layout.FormTableLayout.superclass.renderItem.apply(this, arguments);
              this .cellContentTpl.append(td,[c.text || c.html || c.value]);
         }
        }
    },
    
    
//  private
    isValidParent :  function (c, target){
        
return   true ;
    }    
});
Ext.Container.LAYOUTS[
' formtable ' =  My.layout.FormTableLayout;
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值