You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
      };
    }
  }
}

修正后的代码实现(满足需求)

关键修改点

  1. 新增按行计算总分的函数,避免全局变量导致的行数据混乱;
  2. 针对「球员姓名」列单独做字符串校验,拒绝纯数字或空输入;
  3. 修复原代码中clientleft拼写错误;
  4. 修改得分列内容后自动重新计算当前行总分;
  5. 简化代码逻辑,拆分初始化、事件绑定、计算功能为独立函数。

修正后的 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:26:00