Roger Withnell wrote:
I would like to freeze column and row headings on a webpage, simulating
freeze panes as in an Excel spreadsheet.
Don't seem to be able to do it with Frames. Is there a way with Javascript
and/or CSS and or Frames?
This is just a start, so you can develop it too, but here is an example developed with YAHOO's javascript UI toolkit:
http://developer.yahoo.com/yui/
Column resizing hits limits where the browser refuses to resize any further. That needs detecting, but this is ongoing development...
Put it into the examples\animation directory:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Animation Example - Size</title>
<style type="text/css">
..Table {
border-collapse:collapse;
}
..Table tbody td {
border:1px solid black;
overflow:hidden;
}
..Table thead th {
white-space:nowrap;
background-color:buttonface;
border:1px inset;
overflow:hidden;
}
</style>
<script type="text/javascript" src="../../build/yahoo/yahoo.js"></script>
<script type="text/javascript" src="../../build/event/event.js"></script>
<script type="text/javascript" src="../../build/dom/dom.js"></script>
<script type="text/javascript"
src="../../build/animation/animation.js"></script>
<script type="text/javascript">
function Table(id, width, height)
{
this.headerTable = document.getElementById(id);
this.tbody = this.headerTable.tBodies[0];
var bodyHeight = this.tbody.offsetHeight;
this.headerContainer = document.createElement("div")
this.headerContainer.style.width = width + "px";
this.headerContainer.style.overflow = "hidden";
this.bodyContainer = document.createElement("div")
var bodyContainerWidth = width;
if (bodyHeight > height)
bodyContainerWidth += 20;
this.bodyContainer.style.width = bodyContainerWidth + "px";
this.bodyContainer.style.height = height + "px";
this.bodyContainer.style.overflow = "auto";
this.headerTable.parentNode.insertBefore(this.head erContainer, this.headerTable);
this.headerTable.parentNode.insertBefore(this.body Container, this.headerTable);
this.headerTable.style.width = this.headerTable.offsetWidth + "px";
this.headerTable.className = "Table";
this.thead = this.headerTable.getElementsByTagName("thead")[0];
this.thead.className = "TableHeader";
YAHOO.util.Dom.generateId(this.thead, "TableHeader");
this.headerRow = this.thead.rows[0];
this.headerCells = this.headerRow.cells;
this.headerColgroup = document.createElement("colgroup");
this.headerTable.insertBefore(this.headerColgroup, this.thead);
for (var i = 0; i < this.headerCells.length; i++)
{
this.headerCells[i].className = "TableHeader";
var col = document.createElement("col");
col.width = this.headerCells[i].offsetWidth;
this.headerColgroup.appendChild(col);
}
this.bodyColgroup = this.headerColgroup.cloneNode(true);
this.bodyTable = document.createElement("table");
this.bodyTable.style.width = this.headerTable.offsetWidth + "px";
this.bodyTable.appendChild(this.bodyColgroup);
this.bodyTable.className = "Table";
this.bodyTable.appendChild(this.tbody);
this.headerContainer.appendChild(this.headerTable) ;
this.bodyContainer.appendChild(this.bodyTable);
var _this = this;
setInterval(function()
{
_this.headerContainer.scrollLeft = _this.bodyContainer.scrollLeft;
}, 50);
this.resizingHeaderIndex = false;
this.headerResizing = false;
this.onHeaderBoundary = false;
this.colResizeStartX;
YAHOO.util.Event.addListener(window, "mousemove", function(e)
{
var x = YAHOO.util.Event.getPageX(e);
if (this.headerResizing)
{
var xDelta = x - this.colResizeStartX;
var colWidth = parseInt(this.headerColgroup.childNodes[this.resizingHeaderIndex].width) + xDelta;
this.headerColgroup.childNodes[this.resizingHeaderIndex].width = colWidth;
this.bodyColgroup.childNodes[this.resizingHeaderIndex].width = colWidth;
var tableWidth = parseInt(YAHOO.util.Dom.getStyle(this.bodyTable, "width")) + xDelta;
this.headerTable.style.width = tableWidth + "px";
this.bodyTable.style.width = tableWidth + "px";
this.colResizeStartX = x;
}
else
{
var t = YAHOO.util.Event.getTarget(e);
if (t.className == "TableHeader")
{
var hLeft = YAHOO.util.Dom.getX(t);
var hRight = hLeft + t.offsetWidth - 2;
if ((x >= (hRight - 1)) && (x <= (hRight + 1)))
{
this.onHeaderBoundary = true;
this.resizingHeaderIndex = t.cellIndex;
document.body.style.cursor = "col-resize";
}
else
{
this.onHeaderBoundary = false;
document.body.style.cursor = "";
}
}
else
{
this.onHeaderBoundary = false;
document.body.style.cursor = "";
}
}
}, this, true);
YAHOO.util.Event.addListener(this.thead, "mousedown", function(e)
{
var t = YAHOO.util.Event.getTarget(e);
if (this.onHeaderBoundary)
{
this.colResizeStartX = YAHOO.util.Event.getPageX(e);
this.headerResizing = true;
}
}, this, true);
YAHOO.util.Event.addListener(window, "mouseup", function(e)
{
this.headerResizing = false;
document.body.style.cursor = "";
}, this, true);
};
function onLoadWindow()
{
new Table("table", 300, 100);
}
YAHOO.util.Event.addListener(window, 'load', onLoadWindow);
</script>
<link rel="stylesheet" type="text/css" href="css/anim.css">
</head>
<body>
<div id="doc">
<h1>Table Example</h1>
<br>
<table id="table" style="overflow:hidden;border:1px solid black">
<thead>
<tr>
<th>Fooooooooooooooo</th>
<th>A very wide column header</th>
<th>Bleeeeeeeeeeeeeeeeeeeeeeeeeeeetch</th>
</tr>
</thead>
<tbody>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
<tr>
<td>Foo data</td>
<td>Wide data..........................................</td>
<td>Bletch data</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
Nige ("exgardianreader")