This script allows you to size a table so that the width of its TDs becomes the same as the width of the TDs of another table, so that the first table can become a header.
This script consists of two parts. First of all, we need to size the header table to
the actual sizes of the TD's in the large table. Thus you can change the large table without
changing the header table: it will always take the correct width.
When that is done we 'fix' the header table by means of the
sticky menu script.
The example is below on this page because it needs a large table.
This is the script:
var stuff = new Array('name','tel','function'); var old,theTop,menu,temp; function scale() { if (temp) clearTimeout(temp); if (!document.all && !document.getElementById) { alert('The script on this page does\'t work in your browser'); return; } var extra = 0; if (document.all) extra = 2; extra +=4; // +2 per point of cellpadding var a = new getObj('fixedtable'); var b = new getObj('normaltable'); for (i=0;i<stuff.length;i++) { y = new getObj(stuff[i]+'body'); z = new getObj(stuff[i]+'head'); x = y.obj.offsetWidth - extra; z.style.width = x; } theTop = b.obj.offsetTop - a.obj.offsetHeight; a.style.left = b.obj.offsetLeft; old=theTop; menu = new getObj('fixedtable'); movemenu(); } window.onresize = scale;
You also need my sticky menu script and the DHTML micro-API. All these scripts work on these two tables:
<DIV ID="fixedtable"> <TABLE border=1 cellpadding=2 cellspacing=0> <TR> <TD ID="namehead">Name</TD> <TD ID="telhead">Telephone</TD> <TD ID="functionhead">Function</TD> </TR> </TABLE> </DIV> <DIV ID="normaltable"> <TABLE border=1 cellpadding=2 cellspacing=0> <TR> <TD ID="namebody">Ms. T.</TD> <TD ID="telbody">secret</TD> <TD ID="functionbody">Senior Capital Venturer</TD> </TR> <TR>lots more TRs</TR> </TABLE> </DIV>
which have the following initial style sheets:
div#fixedtable {position: relative; padding: 0px; z-index: 5; } div#normaltable {position: relative; margin-left: 10% }
There are two separate tables in your HTML: the header table and the content table. I put the tables inside DIVs because it turns out that Netscape 6 has a bug that makes it impossible to change the top and left of tables, something we'll want to do later on. Using DIVs evades that problem. We give both DIVs an ID. and give them both a relative position. This is because we want to influence the position of the tables later on. Also, the header table should have a higher z-index than the content table because it should be shown on top of it.
Both the header table and the content table should have IDs for individual cells. As usual, I've chosen a definite naming system. There are three columns in both tables, name, tel and function. The IDs of the header table get head behind these names, those of the content table get body behind it. We also store the three names in a JavaScript array and define some more variables we'll need:
var stuff = new Array('name','tel','function'); var old,theTop,menu,temp;
Then to the function scale(). It is for correctly scaling the widths of the TDs of the header table to the widths of the TDs of the content table. I call it in a link but you could also call it onLoad.
function scale() {
First of all, if there is already a timeout for fixing the table, cancel it. I explain the timeout below.
if (temp) clearTimeout(temp);
Then support detection. If neither document.all nor document.getElementById is supported (= if the browser is Netscape 4 or worse), the browser is too old and the script should end.
if (!document.all && !document.getElementById) { alert('The script on this page does\'t work in your browser'); return; }
Now we can start. First of all, we need a variable extra to subtract from the TD width later on. Initially it is 0.
var extra = 0;
However, if the browser is Explorer on Windows, it needs to be 2. (Why? I have no idea, I determined this value experimentally)
if (document.all && navigator.userAgent.indexOf('Win') != -1) extra = 2;
Furthermore, for every point of CELLPADDING you give to the tables, 2 should be added to extra. Since in my example the tables have a CELLPADDING of 2, we add 4:
extra +=4; // +2 per point of cellpadding
Then we create new objects for both tables by using the DHTML micro-API. a now contains the header table, b the content table.
var a = new getObj('fixedtable'); var b = new getObj('normaltable');
Then we're ready for the actual scaling. We go through the array stuff which contains the basic names of the TDs.
for (i=0;i<stuff.length;i++) {
We take one TD in the content table (by adding body to the name) and the corresponding TD in the header table (by adding head to the name) and put them in y and z.
y = new getObj(stuff[i]+'body'); z = new getObj(stuff[i]+'head');
Now we calculate the width the TD in the header table should become. This is the offsetWidth of the content table TD minus extra. We set the width of the header table TD to this value. (For offset, see the Get styles page).
x = y.obj.offsetWidth - extra; z.style.width = x; }
When all TDs have the correct width, we still have to move the tables themselved a little bit. Both tables should remain at the same place they are, but the header table should get an absolute position (so we can move it later on). When this is done, the content table moves up a bit to fill the gap that the header table has left in the natural flow of the page. We don't want that, we want the table to remain where it was.
So first of all we calculate where the header table should come. We take the current top of the content table (b.obj.offsetTop) and subtract from it the height of the header table (a.obj.offsetHeight). This is the top of the header table.
theTop = b.obj.offsetTop - a.obj.offsetHeight;
We set the left of the header table to the same amount as the left of the content table, so it respects the margins
a.style.left = b.obj.offsetLeft;
Now that both tables are in position, we have to turn to the sticky menu script for keeping the header table in its correct position. I don't use exactly the same script: the checkbox is missing because it's not necessary.
To pave the way for this function we set some variables that it expects. It uses theTop, which we've also used in this script. old becomes the current top of the header table:
old=theTop;
menu becomes the header table itself:
menu = new getObj('fixedtable');
and we call movemenu()
movemenu(); }
Finally, we have to make sure that the widths of the TDs are recalculated when the user resizes the browser window.
window.onresize = scale;
That's it, you have a working fixed table header.
Back to the top.
Below is the table with phone numbers of all our people. Scale the header table and fix it.
Name | Telephone | Function |
The Bo$$ | (to be reached through his secretary) | Our gracious leader, informed, well-spoken, judicious, He Who Guides, Strong Arm of the Business, Offender of the Faithful, Protractor of the Useless, mystical, mythical, arcane, may his working days be long and his wealth increase |
Dr. Markbrand | ++46.32.191883 | Customer Care Server |
'Manuel' | ++.89.23844.37222 | Cousin of Pedro |
'Pedro' | ++.89.23844.37221 | Cousin of Manuel |
Helly Marshdown | 525.9910 | Incompatibility Manager |
The Archimandrite | 914-20339 | Religious leader, competitor of The Primate |
The Primate | 915-20339 | Religious leader, competitor of The Archimandrite |
Lord Faintheart | 1904 | Chairman of the Vague Board |
Maxwell | 8838 (home) or 7402 (mistress) | Co-worker |
John Street | 8302 | Snooker referee |
Dr. Grävestein | 0 | Fruitologist |
Ms. T. | secret | Senior Capital Venturer |
Augustus | 2714 | Dead Roman Emperor |
Claude | 4154 | Claims to be a dead Roman Emperor. |
Mohammed al-Jawri | to be ascertained | Currently asleep, function to be determined onWakeup |
flock of geese | Can be reached through The Capitol, Rome | Security |
Kiwulu Asampa | Doesn't have one (religous reasons) |
He's the guy sitting on the ground in the disused office on the fifth floor |
Albert Einstein | 194024205 | Inventor of relations |
Ernst Schrödinger | 234239420 | Inventor of cat abuse |
Niels Bohr | 3948234 | Inventor of the dice |
Sir Isaac Newton | q14892048 | Inventor of the apple |
Steve Jobs | 03948-3 | Inventor of the Apple |
Mongo | none | Pawn in game of life |
One problem with the relatively positioned table: it may go over the paragraph below it, which is positioned as if the table weren't slightly moved. I solved this by inserting two <BR>'s below the table.
Back to the top.