JavaScript实现表格特定列求和至PTS及球员信息验证需求
球员得分表格功能实现问题
需求说明
- 计算表格中Sc1pts到Sc10pts列的数值总和,将结果显示在对应行的PTS列中,求和时排除「球衣号码」和「球员姓名」列;
- 「球员姓名」列必须输入字符串,若输入非字符串内容,清空该单元格并弹出提示:请输入姓名。
我已经尝试了近三小时仍未实现上述功能,以下是当前的代码实现:
当前代码实现
HTML 代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"> <title>球员得分统计</title> </head> <body> <h1>运动赛事得分更新</h1> <div class="table-containers"> <table id="table"> <thead> <tr> <th>球衣号码</th> <th>球员姓名</th> <th>Sc1pts</th> <th>Sc2pts</th> <th>Sc3pts</th> <th>Sc4pts</th> <th>Sc5pts</th> <th>Sc6pts</th> <th>Sc7pts</th> <th>Sc8pts</th> <th>Sc9pts</th> <th>Sc10pts</th> <th>总分(PTS)</th> </tr> </thead> <tbody> <tr> </tr> </tbody> </table> <button type="button" onclick="addPlayer()">添加球员</button> </div> <div class="table-containers"> <table id="table1"> <thead> <tr> <th>球衣号码</th> <th>球员姓名</th> <th>Sc1pts</th> <th>Sc2pts</th> <th>Sc3pts</th> <th>Sc4pts</th> <th>Sc5pts</th> <th>Sc6pts</th> <th>Sc7pts</th> <th>Sc8pts</th> <th>Sc9pts</th> <th>Sc10pts</th> <th>总分(PTS)</th> </tr> </thead> <tbody> <tr> </tr> </tbody> </table> <button id="addTable" type="button" onclick="addPlayer1()">添加球员</button> </div> <script src="index.js"></script> </body> </html>
CSS 代码
* { margin: 0; padding: 0; justify-content: center; align-items: center; text-align: center; justify-items: center; } body { font-family: sans-serif; justify-content: center; align-items: center; text-align: center; justify-items: center; } table, thead, tr, th { border: 1px solid black; border-collapse: collapse; padding: 5px; } table, tbody, tr, td { border: 1px solid black; border-collapse: collapse; padding: 5px; } table { margin-left: auto; margin-right: auto; } tr:nth-child(even) { background-color: white; } th { background-color: gray; color: white; } button { margin: 20px; background-color: antiquewhite; border: solid 1px black; border-radius: 5px; padding: 5px; } h1 { margin: 2%; } .table-containers { margin: 5%; }
JavaScript 代码
var add = []; var sum = 0; var addNum = []; function addPlayer() { var table = document.getElementById("table"); var cells = table.querySelectorAll("td"); var row = table.insertRow(); var count = []; for (i = 0; i < 13; i++) { cells = row.insertCell(i); if (i > 1) { cells = cells.innerHTML = "0"; } } addEvents(row); } function addPlayer1() { var table = document.getElementById("table1"); var row = table.insertRow(); for (i = 0; i < 13; i++) { cells = row.insertCell(i); if (i > 1) { cells = cells.innerHTML = "0"; } } addEvents(row); } function addEvents(row) { let cells = row.cells; for (i = 0; i < cells.length; i++) { if (cells[i] != cells[12]) { cells[i].onclick = function() { if (this.hasAttribute("data-clicked")) { return; } this.setAttribute("data-clicked", "yes"); this.setAttribute("data-text", this.innerHTML); var input = document.createElement("input"); input.setAttribute("type", "text"); input.value = this.innerHTML; input.style.width = this.offsetWidth - this.clientLeft * 2 + "px"; input.style.height = this.offsetHeight - this.clientTop * 2 + "px"; input.style.border = "0px"; input.style.fontFamily = "inherit"; input.style.fontSize = "inherit"; input.style.textAlign = "inherit"; input.style.backgroundColor = "LightGoldenRodYellow"; input.onblur = function() { var td = input.parentElement; var orig_text = input.parentElement.getAttribute("data-text"); var current_text = this.value; orig_text = parseInt(orig_text); current_text = parseInt(current_text); if (orig_text != current_text) { if (isNaN(current_text)) { alert("请输入数字"); td.removeAttribute("data-clicked"); td.removeAttribute("data-text"); td.innerHTML = ""; td.style.cssText = "padding: 5px"; } else { td.removeAttribute("data-clicked"); td.removeAttribute("data-text"); td.innerHTML = current_text; td.style.cssText = "padding: 5px"; if (orig_text < current_text || cells[i] != cells[1]) { sum += current_text; console.log(sum); } else if (orig_text > current_text) { current_text = orig_text - current_text; sum -= current_text; console.log(sum); } } } else { td.removeAttribute("data-clicked"); td.removeAttribute("data-text"); td.innerHTML = orig_text; td.style.cssText = "padding: 5px"; if (orig_text < current_text && cells[i] > cells[1]) { sum += current_text; console.log(sum); } else if (orig_text > current_text && cells[i] > cells[1]) { current_text = orig_text - current_text; sum -= current_text; console.log(sum); } } }; input.addEventListener("keypress", function(event) { if (event.key == "Enter") { this.blur(); } }); this.innerHTML = ""; this.style.cssText = "padding: 0px 0px"; this.append(input); this.firstElementChild.select(); }; } } }
修正后的代码实现(满足需求)
关键修改点
- 新增按行计算总分的函数,避免全局变量导致的行数据混乱;
- 针对「球员姓名」列单独做字符串校验,拒绝纯数字或空输入;
- 修复原代码中
clientleft拼写错误; - 修改得分列内容后自动重新计算当前行总分;
- 简化代码逻辑,拆分初始化、事件绑定、计算功能为独立函数。
修正后的 JavaScript 代码
// 为表格1添加球员 function addPlayer() { const table = document.getElementById("table"); const row = table.insertRow(); initRowCells(row); addEvents(row); } // 为表格2添加球员 function addPlayer1() { const table = document.getElementById("table1"); const row = table.insertRow(); initRowCells(row); addEvents(row); } // 初始化行单元格内容 function initRowCells(row) { for (let i = 0; i < 13; i++) { const cell = row.insertCell(i); // 得分列默认填充0,其他列留空 if (i > 1) cell.innerHTML = "0"; } } // 为单元格绑定编辑事件 function addEvents(row) { const cells = row.cells; // 遍历除PTS外的所有单元格 for (let i = 0; i < cells.length - 1; i++) { cells[i].onclick = function() { if (this.hasAttribute("data-clicked")) return; this.setAttribute("data-clicked", "yes"); this.setAttribute("data-text", this.innerHTML); const input = document.createElement("input"); input.type = "text"; input.value = this.innerHTML; input.style.width = `${this.offsetWidth - this.clientLeft * 2}px`; input.style.height = `${this.offsetHeight - this.clientTop * 2}px`; input.style.border = "0"; input.style.fontFamily = "inherit"; input.style.fontSize = "inherit"; input.style.textAlign = "inherit"; input.style.backgroundColor = "LightGoldenRodYellow"; // 失去焦点时处理输入内容 input.onblur = function() { const td = this.parentElement; const origText = td.getAttribute("data-text"); const currentText = this.value.trim(); // 球员姓名列校验 if (td === cells[1]) { if (!currentText || !isNaN(parseInt(currentText))) { alert("请输入姓名"); td.innerHTML = ""; } else { td.innerHTML = currentText; } } // 球衣号、得分列校验 else { const currentNum = parseInt(currentText); if (isNaN(currentNum)) { alert("请输入数字"); td.innerHTML = origText; } else { td.innerHTML = currentNum; // 修改得分列后重新计算总分 if (i >= 2 && i <= 11) calculateRowTotal(row); } } // 清理标记属性 td.removeAttribute("data-clicked"); td.removeAttribute("data-text"); td.style.padding = "5px"; }; // 回车触发失去焦点 input.addEventListener("keypress", e => { if (e.key === "Enter") this.blur(); }); // 替换单元格为输入框 this.innerHTML = ""; this.style.padding = "0"; this.appendChild(input); input.select(); }; } } // 计算当前行总分并更新PTS列 function calculateRowTotal(row) { const cells = row.cells; let total = 0; // 遍历Sc1pts到Sc10pts列(索引2-11) for (let i = 2; i <= 11; i++) { total += parseInt(cells[i].innerHTML) || 0; } cells[12].innerHTML = total; }
内容的提问来源于stack exchange,提问作者Ralph Jenrey Loquellano
相关产品推荐
相关产品推荐

