Static/sticky Header 使用动态 Table
Static/sticky Header Using Dynamic Table
有人可以指导我如何为这个动态创建的 table 实现静态(粘性)header 吗?
一段时间以来,我已经从 Whosebug 线程中尝试了多种方法,但缺乏 HTML/CSS 知识,而且我显然遗漏了一些简单的东西。
我已经设法使用直接在代码的主要 body 中创建的 table 使其工作,但是当我使用从 [=30 动态创建的 table 时=] 我什么也得不到 'stick'.
代码下方:
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=0.50, maximum-scale=1, user-scalable=0"/>
<head>
<title>iNews HTML Running Order</title>
<style>
table
{
border: solid 1px #CCCCCC;
border-collapse: collapse;
text-align: left;
font:30px Arial;
}
tr, th, td
{
white-space: nowrap;
padding-right: 50px;
}
tr
{
background-color: #ffffff;
border: solid 1px #CCCCCC;
}
th
{
background-color: #CCCCCC;
}
#container
{
text-align: center;
max-width: 100%;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body onload="initialisePage('LW')">
<p id="showData">Loading Running Order...</p>
</body>
<script>
var loop;
var filename;
var table;
function updateJSONData(filename)
{
getDataFromJSON(filename)
loop = setInterval(function(){getDataFromJSON(filename);}, 500);
}
function initialisePage(newFilename)
{
filename = newFilename;
updateJSONData(filename)
}
function setFileName(newFilename)
{
clearInterval(loop)
filename = newFilename;
updateJSONData(filename)
}
function getDataFromJSON(filename)
{
$.get( "http://10.142.32.72/dashboard/"+filename+".json", function( data ) {
var myBooks = JSON.parse(data);
CreateTableFromJSON(myBooks)
});
}
function CreateTableFromJSON(myBooks)
{
var title = ["Page", "Slug", "Pres 1", "Pres 2", "CAM", "Format", "Clip Dur", "Total", "Backtime"];
var col = ["page-number", "title", "pres1", "pres2", "camera", "format", "runs-time", "total-time", "back-time"];
// CREATE DYNAMIC TABLE.
table = document.createElement("table");
// CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE.
var tr = table.insertRow(-1); // TABLE ROW.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
th.innerHTML = title[i];
tr.appendChild(th);
}
// ADD JSON DATA TO THE TABLE AS ROWS.
for (var i = 0; i < myBooks.length; i++) {
tr = table.insertRow(-1);
if (myBooks[i]["floated"] == "true"){
tr.style.color = "#ffffff";
tr.style.background = "blue";
}
if ((myBooks[i]["break"] == "true") && (myBooks[i]["floated"] == "false")){
tr.style.background = "#00ff00";
}
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = myBooks[i][col[j]];
}
}
// FINALLY ADD THE NEWLY CREATED TABLE WITH JSON DATA TO A CONTAINER.
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
console.log("Refreshed: " + filename);
}
</script>
</html>
非常感谢,
乔
删除 <body onload="initialisePage('LW')">
并使用 DOMContentLoaded
代替,因为它比文档 load
事件发生得早得多。
load
is only fired after ALL resources/content has been loaded, including "non-essential" (non-DOM) content like images and external content like ad-banners, which means the load
event may be fired tens-of-seconds after DOMContentLoaded
这使得 load
事件今天有点没用了)。
将您的 CSS 更改为:
table > thead > tr > th {
position: sticky;
top: 0;
z-index: 10;
}
table > tbody > tr.floated {
color: '#ffffff';
background-color: 'blue';
}
table > tbody > tr.broken {
background-color: '#00ff00';
}
JavaScript 对函数、值(变量和参数)和属性使用 camelCase
,而不是 PascalCase
。
- 避免
var
并在适当的情况下在脚本中使用 const
和 let
。请注意,const
表示 "unchanging reference"(有点像 C++);它 而不是 意味着 "immutable" 或 "compile-time constant value"。我认为 const
的这个定义是 JavaScript 语言设计者的错误,但这只是我的意见,伙计。
- 通过
classList
使用 CSS 类 而不是使用 .style
. 设置单独的样式属性
- 现在的JavaScript生态也普遍使用1TBS instead of the Allman style.
- 首选
===
(完全等于)而不是 ==
(等于),因为 JavaScript 的 类型强制转换 可能令人惊讶) .
- 尽可能避免使用
innerHTML
。使用 .textContent
设置普通文本内容(也避免使用 .innerText
)。滥用 innerHTML
会导致 XSS 漏洞。
- 2020 年了。停止使用 JQUERY!!!!!!!!!!!
- 不要在您的 JAVASCRIPT 评论中全部使用大写字母,因为它看起来像作者在不必要地对您大喊大叫,并且这会让其他读者感到非常恼火ARRRRGGHHHHH
- 您需要正确处理 HTTP 请求响应(例如,使用正确的
Content-Type
检查成功的响应)。
- 避免使用
j
作为可迭代变量名,因为它在视觉上与 i
. 过于相似
将您的 JavaScript 更改为:
<script>
// You should put all of your own application-specific top-level page script variables in their own object so you can easily access them separately from the global `window` object.
const myPageState = {
loop : null,
fileName: null,
table : null
};
window.myPageState = myPageState; // In the top-level function, `const` and `let`, unlike `var`, do not create a global property - so you need to explicitly set a property like so: `window.{propertyName} = ...`.
window.addEventListener( 'DOMContentLoaded', onDOMLoaded );
function onDOMLoaded( ev ) {
window.myPageState.fileName = "LW";
window.myPageState.loop = setInterval( refreshTable, 500 );
}
async function refreshTable() {
if( typeof window.myPageState.fileName !== 'string' || window.myPageState.fileName.length === 0 ) return;
const url = "http://10.142.32.72/dashboard/" + window.myPageState.fileName + ".json";
const resp = await fetch( url );
if( resp.status === 200 && resp.headers['ContentType'] === 'application/json' ) {
const deserialized = await resp.json();
ceateAndPopulateTableFromJSONResponse( deserialized );
}
else {
// Error: unexpected response.
// TODO: error handling
// e.g. `console.error` or `throw new Error( "Unexpected response." )`, etc.
}
}
function ceateAndPopulateTableFromJSONResponse( myBooks ) {
// TODO: Verify the `myBooks` object layout (i.e. schema-verify `myBooks`).
const columnTitles = ["Page", "Slug", "Pres 1", "Pres 2", "CAM", "Format", "Clip Dur", "Total", "Backtime"];
const columnNames = ["page-number", "title", "pres1", "pres2", "camera", "format", "runs-time", "total-time", "back-time"];
const table = window.myPageState.table || document.createElement( 'table' );
if( window.myPageState.table !== table ) {
window.myPageState = table;
document.getElementById("showData").appendChild( table );
}
// Create the <thead>, if nnecessary:
if( table.tHead === null )
{
table.tHead = document.createElement( 'thead' );
const tHeadTR = table.tHead.insertRow(-1);
for( let i = 0; i < columnNames.length; i++ ) {
const th = document.createElement('th');
th.textContent = columnTitles[i];
tHeadTR.appendChild( th );
}
}
// Clear any existing tbody:
while( table.tBodies.length > 0 ) {
table.removeChild( table.tBodies[0] );
}
// Populate a new <tbody>:
{
const tbody = document.createElement('tbody');
for( let i = 0; i < myBooks.length; i++ ) {
const tr = table.insertRow(-1);
tr.classList.toggle( 'floated', myBooks[i]["floated"] === "true" );
tr.classList.toggle( 'broken' , myBooks[i]["break" ] === "true" && myBooks[i]["floated"] === "false" );
for( let c = 0; c < columnNames.length; c++ ) {
const td = tr.insertCell(-1);
const colName = columnNames[c];
td.textContent = myBooks[i][ colName ];
}
}
table.appendChild( tbody );
}
console.log( "Refreshed: " + window.myPageState.fileName );
}
</script>
有人可以指导我如何为这个动态创建的 table 实现静态(粘性)header 吗?
一段时间以来,我已经从 Whosebug 线程中尝试了多种方法,但缺乏 HTML/CSS 知识,而且我显然遗漏了一些简单的东西。
我已经设法使用直接在代码的主要 body 中创建的 table 使其工作,但是当我使用从 [=30 动态创建的 table 时=] 我什么也得不到 'stick'.
代码下方:
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=0.50, maximum-scale=1, user-scalable=0"/>
<head>
<title>iNews HTML Running Order</title>
<style>
table
{
border: solid 1px #CCCCCC;
border-collapse: collapse;
text-align: left;
font:30px Arial;
}
tr, th, td
{
white-space: nowrap;
padding-right: 50px;
}
tr
{
background-color: #ffffff;
border: solid 1px #CCCCCC;
}
th
{
background-color: #CCCCCC;
}
#container
{
text-align: center;
max-width: 100%;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body onload="initialisePage('LW')">
<p id="showData">Loading Running Order...</p>
</body>
<script>
var loop;
var filename;
var table;
function updateJSONData(filename)
{
getDataFromJSON(filename)
loop = setInterval(function(){getDataFromJSON(filename);}, 500);
}
function initialisePage(newFilename)
{
filename = newFilename;
updateJSONData(filename)
}
function setFileName(newFilename)
{
clearInterval(loop)
filename = newFilename;
updateJSONData(filename)
}
function getDataFromJSON(filename)
{
$.get( "http://10.142.32.72/dashboard/"+filename+".json", function( data ) {
var myBooks = JSON.parse(data);
CreateTableFromJSON(myBooks)
});
}
function CreateTableFromJSON(myBooks)
{
var title = ["Page", "Slug", "Pres 1", "Pres 2", "CAM", "Format", "Clip Dur", "Total", "Backtime"];
var col = ["page-number", "title", "pres1", "pres2", "camera", "format", "runs-time", "total-time", "back-time"];
// CREATE DYNAMIC TABLE.
table = document.createElement("table");
// CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE.
var tr = table.insertRow(-1); // TABLE ROW.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
th.innerHTML = title[i];
tr.appendChild(th);
}
// ADD JSON DATA TO THE TABLE AS ROWS.
for (var i = 0; i < myBooks.length; i++) {
tr = table.insertRow(-1);
if (myBooks[i]["floated"] == "true"){
tr.style.color = "#ffffff";
tr.style.background = "blue";
}
if ((myBooks[i]["break"] == "true") && (myBooks[i]["floated"] == "false")){
tr.style.background = "#00ff00";
}
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = myBooks[i][col[j]];
}
}
// FINALLY ADD THE NEWLY CREATED TABLE WITH JSON DATA TO A CONTAINER.
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
console.log("Refreshed: " + filename);
}
</script>
</html>
非常感谢,
乔
删除
<body onload="initialisePage('LW')">
并使用DOMContentLoaded
代替,因为它比文档load
事件发生得早得多。load
is only fired after ALL resources/content has been loaded, including "non-essential" (non-DOM) content like images and external content like ad-banners, which means theload
event may be fired tens-of-seconds afterDOMContentLoaded
这使得load
事件今天有点没用了)。
将您的 CSS 更改为:
table > thead > tr > th { position: sticky; top: 0; z-index: 10; } table > tbody > tr.floated { color: '#ffffff'; background-color: 'blue'; } table > tbody > tr.broken { background-color: '#00ff00'; }
JavaScript 对函数、值(变量和参数)和属性使用
camelCase
,而不是PascalCase
。- 避免
var
并在适当的情况下在脚本中使用const
和let
。请注意,const
表示 "unchanging reference"(有点像 C++);它 而不是 意味着 "immutable" 或 "compile-time constant value"。我认为const
的这个定义是 JavaScript 语言设计者的错误,但这只是我的意见,伙计。 - 通过
classList
使用 CSS 类 而不是使用.style
. 设置单独的样式属性
- 现在的JavaScript生态也普遍使用1TBS instead of the Allman style.
- 首选
===
(完全等于)而不是==
(等于),因为 JavaScript 的 类型强制转换 可能令人惊讶) . - 尽可能避免使用
innerHTML
。使用.textContent
设置普通文本内容(也避免使用.innerText
)。滥用innerHTML
会导致 XSS 漏洞。 - 2020 年了。停止使用 JQUERY!!!!!!!!!!!
- 不要在您的 JAVASCRIPT 评论中全部使用大写字母,因为它看起来像作者在不必要地对您大喊大叫,并且这会让其他读者感到非常恼火ARRRRGGHHHHH
- 您需要正确处理 HTTP 请求响应(例如,使用正确的
Content-Type
检查成功的响应)。 - 避免使用
j
作为可迭代变量名,因为它在视觉上与i
. 过于相似
将您的 JavaScript 更改为:
<script> // You should put all of your own application-specific top-level page script variables in their own object so you can easily access them separately from the global `window` object. const myPageState = { loop : null, fileName: null, table : null }; window.myPageState = myPageState; // In the top-level function, `const` and `let`, unlike `var`, do not create a global property - so you need to explicitly set a property like so: `window.{propertyName} = ...`. window.addEventListener( 'DOMContentLoaded', onDOMLoaded ); function onDOMLoaded( ev ) { window.myPageState.fileName = "LW"; window.myPageState.loop = setInterval( refreshTable, 500 ); } async function refreshTable() { if( typeof window.myPageState.fileName !== 'string' || window.myPageState.fileName.length === 0 ) return; const url = "http://10.142.32.72/dashboard/" + window.myPageState.fileName + ".json"; const resp = await fetch( url ); if( resp.status === 200 && resp.headers['ContentType'] === 'application/json' ) { const deserialized = await resp.json(); ceateAndPopulateTableFromJSONResponse( deserialized ); } else { // Error: unexpected response. // TODO: error handling // e.g. `console.error` or `throw new Error( "Unexpected response." )`, etc. } } function ceateAndPopulateTableFromJSONResponse( myBooks ) { // TODO: Verify the `myBooks` object layout (i.e. schema-verify `myBooks`). const columnTitles = ["Page", "Slug", "Pres 1", "Pres 2", "CAM", "Format", "Clip Dur", "Total", "Backtime"]; const columnNames = ["page-number", "title", "pres1", "pres2", "camera", "format", "runs-time", "total-time", "back-time"]; const table = window.myPageState.table || document.createElement( 'table' ); if( window.myPageState.table !== table ) { window.myPageState = table; document.getElementById("showData").appendChild( table ); } // Create the <thead>, if nnecessary: if( table.tHead === null ) { table.tHead = document.createElement( 'thead' ); const tHeadTR = table.tHead.insertRow(-1); for( let i = 0; i < columnNames.length; i++ ) { const th = document.createElement('th'); th.textContent = columnTitles[i]; tHeadTR.appendChild( th ); } } // Clear any existing tbody: while( table.tBodies.length > 0 ) { table.removeChild( table.tBodies[0] ); } // Populate a new <tbody>: { const tbody = document.createElement('tbody'); for( let i = 0; i < myBooks.length; i++ ) { const tr = table.insertRow(-1); tr.classList.toggle( 'floated', myBooks[i]["floated"] === "true" ); tr.classList.toggle( 'broken' , myBooks[i]["break" ] === "true" && myBooks[i]["floated"] === "false" ); for( let c = 0; c < columnNames.length; c++ ) { const td = tr.insertCell(-1); const colName = columnNames[c]; td.textContent = myBooks[i][ colName ]; } } table.appendChild( tbody ); } console.log( "Refreshed: " + window.myPageState.fileName ); } </script>