• Hi,
    I think there's a problem with the table layout. I try to do a 3 by 4 table with elements that have rowspans and colspans defined. The layout is not generated correctly though. The 2nd line has 5 columns instead of 4.

    I have the following piece of code:

    layout: 'table',
    layoutConfig: {
    columns: 4
    },
    items: [
    {
    rowspan: 3,
    html: "firstColumn"
    },{
    colspan: 3,
    html: "firstRow"
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"Range", hideLabel: true,name:"radio1"})
    },{
    layout: 'form',
    items: new Ext.form.NumberField({fieldLabel:"From",width:50})
    },{
    layout: 'form',
    items: new Ext.form.NumberField({fieldLabel:"To",width:50})
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"List", hideLabel: true,name:"radio1"})
    },{
    colspan: 2,
    layout: 'form',
    items: [new Ext.form.TextField({width:100})]
    }
    ]

    This code is nested in the row of another table, but I don't think that's part of the problem..

    Jo


  • Can you please retest using this updated patch? Note that this code actually includes the patch plus an extensive test case. You should be able to drop this entire block into an empty test page and run it. If you find any problems, please provide a test case showing the issue.

    Ext.onReady(function(){
    Ext.override(Ext.layout.TableLayout, {
    setContainer : function(ct){
    Ext.layout.TableLayout.superclass.setContainer.cal l(this, ct);

    this.currentRow = 0;
    this.currentColumn = 0;
    this.spanCells = ;
    },
    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){
    //we are on a new row
    this.currentRow = cell[1];
    if(c.colspan){
    //since the col index is now set at the start of the
    //new cell, any colspan needs to get reapplied. This is
    //only necessary if the row changed since the col index
    //only gets reset in that case
    this.currentColumn += c.colspan - 1;
    }
    }
    row = this.getRow(this.currentRow);
    }
    if(c.colspan){
    td.colSpan = c.colspan;
    }
    if(c.cellId){
    td.id = c.cellId;
    }
    td.className = 'x-table-layout-cell';
    if(c.cellCls){
    td.className += ' ' + c.cellCls;
    }
    if(c.rowspan){
    td.rowSpan = c.rowspan;
    var rowIndex = this.currentRow, colspan = c.colspan 1;
    //track rowspanned cells to include in the column count 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(++c > this.columns){
    //exceeded column count, so reset to the start of the next row
    return this.getNextNonSpan(1, ++r);
    }
    }else{
    break;
    }
    }
    return [c,r];
    }
    });

    // TEST CASES:
    var w = new Ext.Window({
    title: 'Table Layout Tests',
    height: 350,
    width: 500,
    border: false,
    layout: 'fit',
    items: [{
    xtype:'tabpanel',
    activeTab: 0,
    enableTabScroll: true,
    layoutOnTabChange: true,
    defaults: {
    bodyStyle: 'padding:10px;'
    },
    items: [{
    title:'Complex Table Form',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:0 5px;'
    },
    layoutConfig: {
    columns: 4
    },
    items: [{
    colspan: 4,
    html: "Header"
    },{
    rowspan: 3,
    html: "firstColumn"
    },{
    colspan: 3,
    html: "firstRow"
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"Range", hideLabel: true,name:"radio1",checked:true})
    },{
    layout: 'form',
    labelWidth: 40,
    items: new Ext.form.NumberField({fieldLabel:"From",width:50})
    },{
    layout: 'form',
    labelWidth: 30,
    items: new Ext.form.NumberField({fieldLabel:"To",width:50})
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"List:", hideLabel: true,name:"radio1"})
    },{
    colspan: 2,
    layout: 'form',
    labelWidth: 40,
    items: [new Ext.form.TextField({width:145, hideLabel: true, anchor:'100%'})]
    },{
    colspan: 3,
    html: "Second set of fields"
    },{
    rowspan: 2,
    html: "Nested
    rowspan"
    },{
    colspan: 3,
    html: "With a Subtitle"
    },{
    rowspan: 3,
    html: "firstColumn"
    },{
    colspan: 3,
    html: "firstRow"
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"Range", hideLabel: true,name:"radio1",checked:true})
    },{
    layout: 'form',
    labelWidth: 40,
    items: new Ext.form.NumberField({fieldLabel:"From",width:50})
    },{
    layout: 'form',
    labelWidth: 30,
    items: new Ext.form.NumberField({fieldLabel:"To",width:50})
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"List:", hideLabel: true,name:"radio1"})
    },{
    colspan: 2,
    layout: 'form',
    labelWidth: 40,
    items: [new Ext.form.TextField({width:145, hideLabel: true, anchor:'100%'})]
    }]
    },{
    title:'Plain Grid',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 5
    },
    items: [
    {html:'1,1'},{html:'1,2'},{html:'1,3'},{html:'1,4' },{html:'1,5'},
    {html:'2,1'},{html:'2,2'},{html:'2,3'},{html:'2,4' },{html:'2,5'},
    {html:'3,1'},{html:'3,2'},{html:'3,3'},{html:'3,4' },{html:'3,5'},
    {html:'4,1'},{html:'4,2'},{html:'4,3'},{html:'4,4' },{html:'4,5'},
    {html:'5,1'},{html:'5,2'},{html:'5,3'},{html:'5,4' },{html:'5,5'}
    ]
    },{
    title:'Rowspans',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 6
    },
    items: [
    {html:'1,1',rowspan:4},{html:'1,2'},{html:'1,3'},{ html:'1,4',rowspan:2},{html:'1,5'},{html:'1,6',row span:3},
    {html:'2,2',rowspan:3},{html:'2,3'},{html:'2,5',ro wspan:3},
    {html:'3,3',rowspan:2},{html:'3,4'},
    {html:'4,4'},{html:'4,5'}
    ]
    },{
    title:'Colspans',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 4
    },
    items: [
    {html:'1,1',colspan:4},
    {html:'2,1'},{html:'2,2'},{html:'2,3'},{html:'2,4' },
    {html:'3,1'},{html:'3,2',colspan:3},
    {html:'4,1',colspan:2},{html:'4,3',colspan:2},
    {html:'5,1'},{html:'5,2',colspan:2},{html:'5,4'},
    {html:'6,1',colspan:4}
    ]
    },{
    title:'Mixed Spanning',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 6
    },
    items: [
    {html:'1,1',colspan:2},{html:'1,3',colspan:2,rowsp an:2},{html:'1,5',rowspan:3},{html:'1,6',rowspan:5 },
    {html:'2,1',rowspan:3},{html:'2,2'},
    {html:'3,2'},{html:'3,3'},{html:'3,4'},
    {html:'4,2',colspan:2,rowspan:2},{html:'4,4'},{htm l:'4,5'},
    {html:'5,1'},{html:'5,4',colspan:2},
    {html:'6,1',colspan:6}
    ]
    }]
    }]
    });
    w.show();
    });


  • {
    title:'Debug Spanning',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 3
    },
    items: [
    {html:'1,1',rowspan:3},{html:'1,2'},{html:'1,3'},
    {html:'2,2',colspan:2},
    {html:'3,2'},{html:'3,3'}
    ]
    }


    try this one, bug still exists in 2.0 final


  • Would you please post a complete file(s) droppable into ext/examples tree?


  • That did it, thank you!


    Will set to thread to resolved.


  • Sorry for the delay. I have a patch that is fully tested and seems to work fine with your code. However, the patch code still needs a bit of refactoring before I post it. This was one of those things where the existing code worked great for 90% of scenarios, but getting those last 10% of scenarios covered was 90% of the effort. 8-


  • Hi jo2008,

    Can you please drop this override into your code and let me know if it fixes the issue for you?


    Ext.override(Ext.layout.TableLayout, {
    spanCells : ,
    getNextCell : function(c){
    var td = document.createElement('td'), row;
    if(!this.columns){
    row = this.getRow(0);
    }else {
    if(this.currentColumn !== 0 && (this.currentColumn % this.columns === 0)){
    row = this.getRow(++this.currentRow);
    this.currentColumn = (c.colspan 0) + (this.spanCells[this.currentRow] 0);
    }else{
    row = this.getRow(this.currentRow);
    this.currentColumn += (c.colspan 1);
    }
    }
    if(c.colspan){
    td.colSpan = c.colspan;
    }
    if(c.cellId){
    td.id = c.cellId;
    }
    td.className = 'x-table-layout-cell';
    if(c.cellCls){
    td.className += ' ' + c.cellCls;
    }
    if(c.rowspan){
    td.rowSpan = c.rowspan;
    var r = this.currentRow;
    //track spanned cells to include in the column count later
    for(i = r+1; i < r+c.rowspan; i++){
    if(this.spanCells[i]){
    this.spanCells[i] += 1;
    }else{
    this.spanCells[i] = 1;
    }
    }
    }
    row.appendChild(td);
    return td;
    }
    });


  • While we're at it.. is it possible to vertical align the contents of table fields?

    I'd like the rowspan>1 fields to display their contents at the top end.

    I've tried setting the style/bodystyle config of the content panel to "vertical-align:top;". I also tried using that settign on the panel that has the table definition...

    What prevents the vertical alignment?

    Jo


  • Great! I'll go ahead and apply the fixes to SVN. Yes, this one was a bit of a pain :s -- but at least its fixed. :D

    Let me know if any other issues crop up with the spanning.


  • Hi Brian,

    I tested the patch both with your test case and with my existing code and both seem to be working fine. I compared your definitions and the resulting examples and I coulnd't find any errors. My table layout code was also rendered correctly now.
    I can understand that even though the html tables seem to be very simple, the calculations behind them are brainwrecking.. So thanks alot for the great work and effort!

    Jo


  • Hi Brian,

    after adding that code, the rowspan problem was fixed in one case where i hit the bug.

    But then another error occured: The surrounding table (one column), that contains 3 tables as items, suddenly messed up its layout by putting the third table next to the second, although the layout config had columns set to 1.

    Independently of this problem, the 3 inner tables didn't expand to the parent's width but only to their elements' width. I tried setting all kinds of style and bodystyle configs to 100% but none of them worked.

    I removed this outer table and used the standard layout since this also has the effect that i wanted. The 3 inner tables are now using the full width.


    I suspect that there is more wrong with the fix though. I tried to adapt another form of mine, consisting of 7 tables, all being items of a Ext.Panel. The tables all use simple rowspan / colspan layouts and are all about 4:3 cells.
    These tables seem to be influencing each other since only some of them are layouted correctly. by editing the order or commenting out some of the tables, other tables' layouts are messed up that were ok before..

    I really can't find any pattern behind this. I even tried copy/pasting one single table and some of the resulting layouts were ok, some were messed up.

    The amount of columns does not exceed the setting anymore, but the messed up tables seem to finish the rows too early.


    Jo


  • You need the alignment style to apply at the TD level for tables. The easiest approach would be to give the TableLayout's containing panel an id then add a CSS rule like this:

    #my-panel td {
    vertical-align:top;
    }


  • Heres the code that i use.. it's a function that returns a panel with all the elements.

    Hope this will be enough to be able to reproduce the effect.

    In my scenario, I put the panel in a Tab control which is inside a border layout of a window.


    Thanks,

    Jo


  • Ext.onReady(function(){
    Ext.override(Ext.layout.TableLayout, {
    setContainer : function(ct){
    Ext.layout.TableLayout.superclass.setContainer.cal l(this, ct);

    this.currentRow = 0;
    this.currentColumn = 0;
    this.spanCells = ;
    },
    getNextCell : function(c){
    var td = document.createElement('td'), row, colIndex, nc;
    if(!this.columns){
    row = this.getRow(0);
    }else {
    colIndex = this.currentColumn;
    if(colIndex !== 0 && (colIndex % this.columns === 0)){
    this.currentRow++;
    colIndex = 0;
    nc = (c.colspan 1);
    }else{
    nc = colIndex + (c.colspan 1);
    }

    for(var ci = colIndex + 1, clen = nc; ci < clen; ci++) {
    if(this.spanCells[ci] && this.spanCells[ci][this.currentRow + 1]) nc++;
    }

    colIndex = nc;

    //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){
    //we are on a new row
    this.currentRow = cell[1];
    if(c.colspan){
    //since the col index is now set at the start of the
    //new cell, any colspan needs to get reapplied. This is
    //only necessary if the row changed since the col index
    //only gets reset in that case
    this.currentColumn += c.colspan - 1;
    }
    }
    row = this.getRow(this.currentRow);
    }
    if(c.colspan){
    td.colSpan = c.colspan;
    }
    if(c.cellId){
    td.id = c.cellId;
    }
    td.className = 'x-table-layout-cell';
    if(c.cellCls){
    td.className += ' ' + c.cellCls;
    }
    if(c.rowspan){
    td.rowSpan = c.rowspan;
    var rowIndex = this.currentRow, colspan = c.colspan 1;
    //track rowspanned cells to include in the column count 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(++c > this.columns){
    //exceeded column count, so reset to the start of the next row
    return this.getNextNonSpan(1, ++r);
    }
    }else{
    break;
    }
    }
    return [c,r];
    }
    });

    // TEST CASES:
    var w = new Ext.Window({
    title: 'Table Layout Tests',
    height: 350,
    width: 500,
    border: false,
    layout: 'fit',
    items: [{
    xtype:'tabpanel',
    activeTab: 0,
    enableTabScroll: true,
    layoutOnTabChange: true,
    defaults: {
    bodyStyle: 'padding:10px;'
    },
    items: [{
    title:'Complex Table Form',
    layout:'table',
    defaults: {
    border:false,
    bodyStyle:'padding:0 5px;'
    },
    layoutConfig: {
    columns: 4
    },
    items: [{
    colspan: 4,
    html: "Header"
    },{
    rowspan: 3,
    html: "firstColumn"
    },{
    colspan: 3,
    html: "firstRow"
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"Range", hideLabel: true,name:"radio1",checked:true})
    },{
    layout: 'form',
    labelWidth: 40,
    items: new Ext.form.NumberField({fieldLabel:"From",width:50})
    },{
    layout: 'form',
    labelWidth: 30,
    items: new Ext.form.NumberField({fieldLabel:"To",width:50})
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"List:", hideLabel: true,name:"radio1"})
    },{
    colspan: 2,
    layout: 'form',
    labelWidth: 40,
    items: [new Ext.form.TextField({width:145, hideLabel: true, anchor:'100%'})]
    },{
    colspan: 3,
    html: "Second set of fields"
    },{
    rowspan: 2,
    html: "Nested
    rowspan"
    },{
    colspan: 3,
    html: "With a Subtitle"
    },{
    rowspan: 3,
    html: "firstColumn"
    },{
    colspan: 3,
    html: "firstRow"
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"Range", hideLabel: true,name:"radio1",checked:true})
    },{
    layout: 'form',
    labelWidth: 40,
    items: new Ext.form.NumberField({fieldLabel:"From",width:50})
    },{
    layout: 'form',
    labelWidth: 30,
    items: new Ext.form.NumberField({fieldLabel:"To",width:50})
    },{
    layout: 'form',
    items: new Ext.form.Radio({boxLabel:"List:", hideLabel: true,name:"radio1"})
    },{
    colspan: 2,
    layout: 'form',
    labelWidth: 40,
    items: [new Ext.form.TextField({width:145, hideLabel: true, anchor:'100%'})]
    }]
    },{
    title:'Plain Grid',
    layout:'table',
    defaults: {
    border:true,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 5
    },
    items: [
    {html:'1,1'},{html:'1,2'},{html:'1,3'},{html:'1,4' },{html:'1,5'},
    {html:'2,1'},{html:'2,2'},{html:'2,3'},{html:'2,4' },{html:'2,5'},
    {html:'3,1'},{html:'3,2'},{html:'3,3'},{html:'3,4' },{html:'3,5'},
    {html:'4,1'},{html:'4,2'},{html:'4,3'},{html:'4,4' },{html:'4,5'},
    {html:'5,1'},{html:'5,2'},{html:'5,3'},{html:'5,4' },{html:'5,5'}
    ]
    },
    {
    title:'Rowspans',
    layout:'table',
    defaults: {
    border:true,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 6
    },
    items: [
    {html:'1,1',rowspan:4},{html:'1,2'},{html:'1,3'},{ html:'1,4',rowspan:2},{html:'1,5'},{html:'1,6',row span:3},
    {html:'2,2',rowspan:3},{html:'2,3'},{html:'2,5',ro wspan:3},
    {html:'3,3',rowspan:2},{html:'3,4'},
    {html:'4,4'},{html:'4,6'}
    ]
    },{
    title:'Colspans',
    layout:'table',
    defaults: {
    border:true,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 4
    },
    items: [
    {html:'1,1',colspan:4},
    {html:'2,1'},{html:'2,2'},{html:'2,3'},{html:'2,4' },
    {html:'3,1'},{html:'3,2',colspan:3},
    {html:'4,1',colspan:2},{html:'4,3',colspan:2},
    {html:'5,1'},{html:'5,2',colspan:2},{html:'5,4'},
    {html:'6,1',colspan:4}
    ]
    },{
    title:'Mixed Spanning',
    layout:'table',
    defaults: {
    border:true,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 6
    },
    items: [
    {html:'1,1',colspan:2},{html:'1,3',colspan:2,rowsp an:2},{html:'1,5',rowspan:3},{html:'1,6',rowspan:5 },
    {html:'2,1',rowspan:3},{html:'2,2'},
    {html:'3,2'},{html:'3,3'},{html:'3,4'},
    {html:'4,2',colspan:2,rowspan:2},{html:'4,4'},{htm l:'4,5'},
    {html:'5,1'},{html:'5,4',colspan:2},
    {html:'6,1',colspan:6}
    ]
    },
    {
    title:'Debug Spanning',
    layout:'table',
    defaults: {
    border:true,
    bodyStyle:'padding:5px 15px;'
    },
    layoutConfig: {
    columns: 3
    },
    items: [
    {html:'1,1',rowspan:3},{html:'1,2'},{html:'1,3'},
    {html:'2,2',colspan:2},
    {html:'3,2'},{html:'3,3'}
    ]
    }
    ]
    }]
    });
    w.show();
    });







  • #If you have any other info about this subject , Please add it free.#
    Your name:
    E-mail:
    Telphone:

    Your comments:


    If you have any other info about [2.0b1][SOLVED] Table layout problem with rowspan/colspan , Please add it free.