获取滚动
亲爱的 Web Team:
我想在我的 Web 页上添加一个 HTML 表元素,该页上的第一个 TR 元素(或者可能是 )是静态的,而其余的 TR 元素(或 )是可以滚动的,这可以实现吗?到目前为止,我已经尝试了为标题创建一个单独的表元素,然后围绕“正文”表包装一个 div 元素,并向样式属性添加“overflow: auto”。我是为专门使用 Internet Explorer 5.0 或更高版本的客户端进行开发,因此不需要跨浏览器兼容。
如果您有解决方案,那么我如何能将其与 ASP.NET DataGrid 相结合?
谢谢,
Christopher Perrins
Web Team 的答复:
如果 Web Team 在每次收到开发人员有关此功能的电子邮件时都可以得到一美元,那么我们就不会总去回味以往纳斯达克指数暴涨时的美好时光了。好了,现在是解决这个问题、并为我们的忠实读者给出满意答案的时候了。无疑,我们想以最佳方式来提供 HTML 行为,以便我们可以附加任何所需的表,甚至是由 ASP.NET DataGrid 发送的表。我们的控件 ScrollTable.htc 可以由您来进行自定义或改进。我们阐释它的工作原理。
首先,通过指定用在表元素上的 CSS 类中的行为属性,来将 scrolltable.htc 附加到该元素。
behavior:url(scrolltable.htc);
在 ondocumentready 事件激发时,该行为会通过调用表上的 cloneNode(false) 创建两个表元素。我们克隆不带有子元素的表,而不是创建新表,以便保留诸如 cellSpacing 和样式之类的属性,而不必手动将每个属性添加至两个新表。我们创建的这两个表元素是,包含测试页中表的第一行的标题和包含所有其他行的正文。将正文表插入 CSS 溢出属性设为自动的容器 DIV,这样就可以在必要时进行滚动了。然后,修改测试页中的表以使其只包含两行。第一行包含一个 TD 和标题表,第二行包含一个带有容器 DIV 的 TD。接下来,将该表第一行中的所有单元格的 offsetWidths 存储在数组 rgWidths 中,以便我们可以设置标题和正文表中的单元格,并使它们保持同步。然后,将该标题行添加到 tblHeader 元素,将正文行添加到 tblBody 元素。接着,将 tblBody 插入容器 DIV。之后,将所有行从表中移除,并插入新的两行,一行用于 tblHeader,另一行用于 tblBody。将这些行添加至正文表和标题表后,将两个表中列的宽度设置为存储在数组中的宽度值。最后,设置一些有关该标题和正文的属性,以使其外观看起来整齐些。
在 TestPage.htm 中,您会看到我们向 TABLE 添加了三个 expando 属性。第一个属性是 bodyHeight,用于设置正文高度。如果不设置该属性,则正文将不会滚动。还有 headerCSS 和 bodyCSS,它们只是使您可以为标题表和正文表指定单独的 CSS 类。
以下是源代码:
ScrollTable.htc
<PUBLIC:ATTACH event="ondocumentready" handler="onDocumentReady" /> <SCRIPT language="JScript"> function onDocumentReady() { // Create elements var tblHeader = this.cloneNode(false); var tblBody = this.cloneNode(false); var divCntr = document.createElement("DIV"); // Get column widths var rgWidths = new Array(); for (var i = 0; i < this.rows[0].cells.length; i++) { rgWidths[i] = this.rows[0].cells[i].offsetWidth; } // Add header row var tbdyHeader = document.createElement("TBODY"); tblHeader.appendChild(tbdyHeader); tbdyHeader.appendChild(this.rows[0].cloneNode(true)); // Add body rows var tbdyBody = document.createElement("TBODY"); tblBody.appendChild(tbdyBody); for (var i = 1; i < this.rows.length; i++) { var oRow = this.rows[i].cloneNode(true); tbdyBody.appendChild(oRow); } // Set up body container divCntr.style.overflow = "auto"; if (this.bodyHeight) divCntr.style.height = this.bodyHeight; divCntr.appendChild(tblBody); // Change existing table for (var i = this.rows.length; i > 0; i--) { this.rows[i-1].removeNode(true); } var tr1 = this.insertRow(); var td1 = tr1.insertCell(); var tr2 = this.insertRow(); var td2 = tr2.insertCell(); td1.appendChild(tblHeader); td2.appendChild(divCntr); // Set column widths of all but the last column for (var i = 0; i < rgWidths.length - 1; i++) { tblHeader.rows[0].cells[i].width = rgWidths[i]; tblBody.rows[0].cells[i].width = rgWidths[i]; } tblHeader.style.fontSize = "100%"; tblHeader.width = "100%"; tblHeader.style.tableLayout = "fixed"; tblHeader.className = this.headerCSS ? this.headerCSS : ""; tblHeader.border = 0; tblBody.style.fontSize = "100%"; tblBody.width = "100%"; tblBody.style.tableLayout = "fixed"; tblBody.className = this.bodyCSS ? this.bodyCSS : ""; tblBody.border = 0; this.cellSpacing = 0; this.cellPadding = 0; } </SCRIPT>
TestPage.htm
<HTML> <HEAD> <STYLE> .tblMain { behavior:url(scrolltable.htc); background-color: highlight; border: 1px solid darkblue; font-family: Verdana; font-size: .8em; } .tblHeader { color: highlighttext; } .tblBody { background-color: #EEEEEE; color: darkblue; } </STYLE> </HEAD> <BODY> <TABLE bodyHeight="100" bodyCSS="tblBody" headerCSS="tblHeader" class="tblMain" width="75%" cellspacing=5 cellpadding=0> <TR> <TD nowrap>Header A</TD> <TD nowrap>Header B</TD> <TD nowrap>Header C</TD> </TR> <TR> <TD>Aaaaaaaaaaaaaaaaaaa</TD><TD>B</TD><TD>Ccccccccccccccccccc</TD> </TR> <TR> <TD>A</TD><TD>Bbbbbbb</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> <TR> <TD>A</TD><TD>B</TD><TD>C</TD> </TR> </TABLE> </BODY> </HTML>