Solved

Column width calculation in a table

Posted on 2002-05-22
22
518 Views
Last Modified: 2012-08-13
I have 2 tables with the same number of columns and i want to align the columns in the 2 tables. The lower table does not have any restriction on the column width and the browser calculates the size of the column according to the text in the cells. I want to assign these widths from a sample row in the lower table to the columns in the upper table so these 2 tables have the columns aligned.

My question is how do i calculate the width of a column. I am dealing with DOM 2 compliant browsers only so all the DOM methods are good for me. If i try to query the width of any column in the lower table with say col.getAttribute("width") it never returns the value after recalculating the width according to the text in the columns.
0
Comment
Question by:iDeb
  • 6
  • 4
  • 4
  • +4
22 Comments
 
LVL 30

Expert Comment

by:third
ID: 7028615
my suggestion is - merge this two tables to form a single table. for it to look like you have two separate tables, put a table row which don't have borders. this way no width calculations needed. you can post your code here and i will help you fix your table. ;-)

0
 
LVL 2

Author Comment

by:iDeb
ID: 7028653
i cannot have a single table.....there is a long explanation for this :) ......but its easier on the audience to assume that they have to be 2 different tables, now how do i align the columns....
0
 
LVL 30

Expert Comment

by:third
ID: 7028700
if you will not put this on a single table, you will have a very slim chance of getting the column of each table always aligned.
0
 
LVL 1

Expert Comment

by:vijayneema
ID: 7029392
You cant do this without mearging the table.
If one of your cell in one table contains more data then it will increase the width of your complete column.

vijayneema
0
 
LVL 19

Expert Comment

by:webwoman
ID: 7029576
You'll never get this to work. Make one table.

You say you can't -- explain why, please. And I'd pretty much guarantee we'll show you how you CAN. ;-)
0
 
LVL 1

Accepted Solution

by:
vijayneema earned 100 total points
ID: 7029640
Hi,

I have a funny, time being idea
Insert a new <TR> in both the tables with some text and maximum width and in invisible mode (using same color as background).

like this :
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<table name="table1" border=1>
     <tr>
          <td>your data11</td>
          <td>your data12</td>
     </tr>
     <tr>
          <td>your data21</td>
          <td>your data22</td>
     </tr>
     <tr>
          <td style="color: #ffffff">123456789012345678901234567890</td>
          <td style="color: #ffffff">123456789012345678901234567890</td>
     </tr>
</table>

<table name="table2" border=1>
     <tr>
          <td>data11</td>
          <td>data12</td>
     </tr>
     <tr>
          <td>data21</td>
          <td>data22</td>
     </tr>
     <tr>
          <td style="color: #ffffff">123456789012345678901234567890</td>
          <td style="color: #ffffff">123456789012345678901234567890</td>
     </tr>
</table>

</BODY>
</HTML>

vijayneema
0
 
LVL 2

Author Comment

by:iDeb
ID: 7029748
ok, here's the problem again.....the upper table serves as the headers to the lower table....before calling me crazy, please note that the lower table is within a div which is scrollable, so essentially we get a table where the data is scrollable but the headers remain static. But unfortunately, the data and the headers do not align.

I found there is an attribute(seemed readonly) called offsetWidth for the td and th elements, but it is only available in IE not in Netscape 6.
0
 
LVL 19

Expert Comment

by:webwoman
ID: 7030642
Been there, tried that.. it NEVER lines up. NEVER.

You certainly can make one table -- repeat the headers every so often. Works for everything, and with the added advantage that they PRINT.
0
 
LVL 5

Expert Comment

by:kcm76
ID: 7035065
Try using the clientwidth property as follows:

max = table1.rows(0).cells(0).clientWidth;          
table2.rows(0).cells(0).style.width = max;

The following code will get the max width for each column in the bottom table and set the width of top table's corresponding column.

ALL THE BEST
KCM

*************
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
<TITLE></TITLE>
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
     
     function setWidth()
     {
          var i, j, max, wt;    
          for (i=0; i < tblTop.cols; i++)
          {
               max = 0;              
               for(j=0; j<tblBottom.rows.length; j++)
               {
                    wt = tblBottom.rows(j).cells(i).clientWidth;                    
                    if ( wt > max)
                         max = wt;
               }
               tblTop.rows(0).cells(i).style.width = max;
          }                    
     }
     
</SCRIPT>
<BODY>
<TABLE id="tblTop" border=1 cellpadding=0 cols=4>
     <TR>
          <TD>COL1 </TD>
          <TD>COL2</TD>
          <TD>COL3</TD>
          <TD id=test>COL4</TD>
     </TR>    
</TABLE>
<DIV id="divtblBottom">
<TABLE id="tblBottom" border=1 cellpadding=0>
     <TR>
          <TD>ALL THE </TD>
          <TD>COLUMNS</TD>
          <TD>OF DIFFERENT</TD>
          <TD>WIDTH</TD>
     </TR>    
     <TR>
          <TD>HOW </TD>
          <TD>ABOUT</TD>
          <TD>THIS</TD>
          <TD>?</TD>
     </TR>
     
     <TR>
          <TD>experts exchange </TD>
          <TD>ABOUT</TD>
          <TD>THIS</TD>
          <TD>?</TD>
     </TR>
</TABLE>
</DIV>
<input type=button value = "Set Width" onclick="setWidth()">
</BODY>
</HTML>
0
 
LVL 19

Expert Comment

by:webwoman
ID: 7035195
You don't know what the second table will be. You can't set the first one until you get the second one, and you don't have that yet. If you set the widths fixed, it's pretty much guaranteed that somebody is going to override your styles, or use larger fonts -- and the tables will NEVER line up. NEVER. They never do. You can set them with the exact same sizes, and put NOTHING in them -- and they'll STILL never line up.

The only way you're going to get neatly aligned headers is to make ONE table or use a java applet of some kind. Maybe.
0
 
LVL 5

Expert Comment

by:kcm76
ID: 7036477
web woman...
how about placing the entire script inside the body tag at the end of second table ie) after loading the second table... and im not setting the width fixed, the script will iterate all the rows for each column to get the max width...then it sets the width to that size.

kcm
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 19

Expert Comment

by:webwoman
ID: 7038306
Max width for who? What font? To work for what browser? You can't rewrite something that's already written -- you have to write the header row BEFORE the rest of the table, or are you using frames? (in which case it's NEVER EVER going to line up...)

You can't have the body tag at the end of the second table... it's already WRITTEN the body tag then. Two body tags is a sure recipe for disaster.
0
 
LVL 2

Author Comment

by:iDeb
ID: 7045356
webwoman,
 The script that kcm has can be invoked onload. So, the 2 tables would have rendered themselves by then and then we try to set the width of the columns individually.

kcm,
 though i've not been able to try out your solution yet, my first impression is it is computation intensive and would affect performance heavily for large tables(the type i have are large)...i will update
0
 
LVL 19

Expert Comment

by:webwoman
ID: 7046249
If the page has loaded, the tables have ALREADY rendered. It will only work (maybe) for IE -- you can't rerender an already completed HTML page in Netscape.

And if your tables are that large, the page is going to take forever -- not only does it have to load, it has to load TWICE. Far from optimal.
0
 
LVL 5

Expert Comment

by:kcm76
ID: 7054777
iDeb/Experts.. any feedback/comments?
0
 
LVL 30

Expert Comment

by:third
ID: 7055133
i'm here just listening but still i'll stick with my answer - can't be done. ;-)
0
 
LVL 19

Expert Comment

by:webwoman
ID: 7055284
I second that. Not possible.
0
 
LVL 5

Expert Comment

by:kcm76
ID: 7055802
third, webwoman...

have u ever tried the code that i posted?

KCM
0
 
LVL 2

Author Comment

by:iDeb
ID: 7155465
OK, sorry about taking a long time to get back.....the solution i have managed to live with( a pretty good one) is a variation of the suggestion from vijayneema...i have added 2 dummy rows to the second table(hid them) and after everything has been rendered, moved the one of these rows to the first table. This along with a few checks for the table widths have done the trick.....i am giving the points to vijayneema......kcm deserves a mention too for effort.....maybe vijayneema can spare a some points....
0
 
LVL 1

Expert Comment

by:vijayneema
ID: 7156245
Ya Sure iDeb,

Can you please give a sample code how you solved this problem.

Thanks
vijayneema
0
 

Expert Comment

by:pglee
ID: 7363422
Here's a solution I came up with for a similar problem. We wanted to have static labels so that the user can scroll the data without losing the colum headings. The user should also able to resize the window without any restrictions.

My workaround has only been tested on ie5.5 and may require some tweaks depending on how you set up your stylesheets. I would recommend this only for intranet sites that use the same browser.

There are two tables. The top table is viewed as column labels and the bottom table is the data for those columns.

I place the top and bottom table in their own iframe so that the top table only displays one row and the bottom table shows as many rows as the user can fit on their screen.

The label table contains two rows containing the same data for each row. The second row is a nowrap version of the first row. Unfortunately in IE, a cell will have it's nowrap attribute disabled when you dynamically set the width.

The data cell contains a hidden version of the labels where the foreground is the same as the background.

Assign id values to the label table and displayed label row and to the data table and the hidden label row. Pass the id's to this funciton:

    function syncWidths(labelTable, labelRow, dataTable, hiddenRow)
    {
        labelTable.style.pixelWidth  = (dataTable.clientWidth);
        hiddenRow.style.lineHeight   = 0;
        labelTable.style.marginRight = "8px";
       
        var hiddenCells = hiddenRow.cells;
        var labelCells  = labelRow.cells;
       
        for(var index = 0; index < hiddenCells.length; index++)
        {
            var currentHidden = hiddenCells[index];
            var currentLabel  = labelCells[index];
           
            // 8 is an arbitrary value that seems to work best.
            currentLabel.style.pixelWidth = (currentHidden.clientWidth - 8);
        }
    }


marginRight compensates for the scrollbar on the datatable. The -8 compensates for discrepencies between pixelWidth and clientWidth. These are arbitrary values that seem to work for our setup.

0
 

Expert Comment

by:autoknowledge
ID: 13436697
I'm about 4 years late on this answer.. (always nice to help the people reading it, since I'm one of them) however, for an IE only solution:

KCM's solution was done very well and I'm not exactly sure if anything has changed in the past few years.

An onload would be the way to go.

Let the bottom table render first.  Then once rendered, ALL of the cells for a given column will have the same width.  It's then just a matter of rerendering the header table again, not the bottom table.  This shouldn't be much computation at all.. it will consist of rerendering one table that consists of one row that has the total number of columsn.

I'm not exactly sure why KCM scrolled through all of the rows to find the max width.  I think it's because he ran the function before the onload.

Onload will show a blinking affect, but it still gives a great result and trust me.. if you only check one cell on the bottom table, this function and rerender will work extremely fast.

I've yet to try this, so don't quote me on it.  I'll try it tonight.  Logic wise.. it seems like a great solution though, and I had been planning on it before double checking here first to find another (quicker) solution.  It seems to be the only solution though, so I will give it a try.

The only thing I'm worried about at this point is the scrollbar giving a minor spacing problem.  I may have to throw in a few customizations for this minor but tedious problem.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

When you need to keep track of a simple list of numbers or strings, the Array object is your most direct tool.  As we saw in my earlier EE Article (http://www.experts-exchange.com/A_3488.html), typical array handling might look like this: (CODE) B…
The task A number given should be formatted for easy reading by separating digits into triads. Format must be made inline via JavaScript, i.e., frameworks / functions are not welcome. So let’s take a number like this “12345678.91¿ and format i…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now