基于layui实现的可编辑、可回车进入下一行的表格

开篇

这篇文章来源于我为别人处理一个问题的代码的简化,因为是简化,效果并不能完全展现出来,代码有许多需要修改的地方。因时间因素,此处不做修改,如果哪天有需要的时候,再把这些代码拿来优化使用吧。

代码功能

  1. 渲染一个表格
  2. 双击单元格可编辑(结果列)
  3. 在结果列点击回车,进入下一行
  4. 当鼠标悬停在结果列时,可出现下拉框

代码实现

javascript 复制代码
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="./layui/css/layui.css" />
    <link rel="stylesheet" href="./layui/formSelects.css" />
    <style>
      #projectSelect {
        margin: 20px;
      }
      .dropdown-select {
        position: absolute;
        z-index: 1000;
        background-color: #fff;
        border: 1px solid #ddd;
        padding: 5px;
      }
    </style>
  </head>
  <body>
    <table
      id="projectSelect"
      class="layui-hide"
      lay-filter="projectFilter"
    ></table>

    <script src="./layui/layui.js"></script>
    <script src="./layui/jquery-3.7.1.min.js"></script>
    <script>
      // 是否点击了单元格
      var isEnter = false;
      // 全局变量,存储当前编辑的行索引
      let currentEditingRowIndex = -1;
      layui.use(["table"], function () {
        var table = layui.table;

        // 示例数据
        var selectedProjects = [
          { 序号: 1, 代码: "1001", 名称: "项目A", 结果: "" },
          { 序号: 2, 代码: "1002", 名称: "项目B", 结果: "" },
          { 序号: 3, 代码: "1003", 名称: "项目C", 结果: "" },
          { 序号: 4, 代码: "1004", 名称: "项目D", 结果: "" },
        ];

        // 加载表格
        function loadTable() {
          table.render({
            elem: "#projectSelect",
            data: selectedProjects,
            cols: [
              [
                { field: "序号", title: "序号", align: "center", width: 60 },
                { field: "代码", title: "代码", align: "center", width: 100 },
                { field: "名称", title: "名称", align: "left", width: 300 },
                {
                  field: "结果",
                  title: "结果",
                  align: "left",
                  width: 250,
                  edit: "text",
                },
              ],
            ],
            height: "full-395",
            done: function () {
              var currDropdown; // 存储当前打开的下拉框
              // 监听表格内所有单元格的 keydown 事件
              $(".layui-table td[data-field='结果']").keydown(function (e) {
                console.log("111");
                if (e.code == "Enter") {
                  isEnter = true;
                }
              });

              $("tr").dblclick(function () {
                var code = $(this).find('td[data-field="代码"]').text();
                var resultoptions = $(this)
                  .find('td[data-field="选项"]')
                  .text();
                var referenceRange = $(this)
                  .find('td[data-field="参考区间"]')
                  .text();
                if (resultoptions) {
                  openOptionDialog(resultoptions, code, function (resultValue) {
                    updateTable("result", code, resultValue, "");
                  });
                }
              });

              // 添加鼠标悬停事件
              $(".layui-table td[data-field='结果']").hover(function () {
                console.log("hover");
                var $this = $(this);
                let options = "张三丰;郭靖;杨过;张无忌";
                // 这里的options应该是动态获取的
                if (options) {
                  $this
                    .attr("contenteditable", "false")
                    .removeAttr("data-edit"); // 禁止编辑并去除 data-edit 属性

                  // 创建下拉框
                  var dropdown = $("<select></select>").css({
                    width: $this.outerWidth(),
                    position: "absolute",
                    zIndex: 1000,
                    backgroundColor: "#fff",
                    border: "1px solid #ddd",
                    padding: "5px",
                  });

                  dropdown.append(
                    $("<option></option>").val("").text("请选择")
                  ); // 默认空选项

                  options.split(";").forEach(function (option) {
                    dropdown.append(
                      $("<option></option>").val(option).text(option)
                    );
                  });

                  // 添加下拉框到单元格
                  $("body").append(dropdown);

                  // 设置下拉框位置
                  console.log("this", $this);
                  var offset = $this.offset();
                  console.log("offset", offset);
                  dropdown.css({
                    top: offset.top + $this.outerHeight(),
                    left: offset.left + 7.5,
                  });

                  // 监听选择事件
                  dropdown.change(function () {
                    var selectedValue = $(this).val();
                    var code = $this
                      .closest("tr")
                      .find('td[data-field="代码"]')
                      .text();
                    updateTable("result", code, selectedValue, "");
                    dropdown.remove(); // 移除下拉框
                    $this.text(selectedValue); // 更新单元格文本
                    $this
                      .attr("contenteditable", "true")
                      .attr("data-edit", "text"); // 恢复编辑并重新添加 data-edit 属性
                  });

                  // 移除上一个单元格的下拉框
                  if (currDropdown) {
                    currDropdown.remove();
                  }

                  currDropdown = dropdown;
                } else {
                  $this
                    .attr("contenteditable", "true")
                    .attr("data-edit", "text"); // 恢复编辑并重新添加 data-edit 属性
                }
              });
            },
          });

          // 监听单元格编辑
          table.on("edit(projectFilter)", function (obj) {
            console.log("edit");
            var data = obj.data;
            var code = data.代码;
            var referenceRange = data.参考区间;
            var value = obj.value; // 得到修改后的值
            updateTable("result", code, value, "");

            // 当点击的是回车键时
            if (isEnter) {
              console.log("enter");
              // 当输入完结果这一项时,点击回车键,自动跳转到下一行的结果这一列
              if (obj.field === "结果") {
                // 更新全局变量,存储当前编辑的行索引
                currentEditingRowIndex = $(obj.tr).data("index"); // 获取当前行的索引
                console.log("currentEditingRowIndex", currentEditingRowIndex);
                // 跳转下一行
                goToNextRow();

                $(this).off("keydown"); // 移除键盘事件监听器
              }
            }
          });
        }

        // 定义函数跳转到下一行
        function goToNextRow() {
          // 获取下一个行的索引
          var nextIndex = currentEditingRowIndex + 1;
          // 获取下一个行的 DOM 元素
          var nextRow = $(".layui-table tr[data-index=" + nextIndex + "]");
          if (nextRow.length > 0) {
            // 模拟点击下一个行的结果列单元格
            nextRow.find('td[data-field="结果"]').click();
          }
          isEnter = false; // 把回车事件标识初始化
        }

        //更新结果或标记标记
        function updateTable(type, code, result, mark, printRang) {
          var tableData = table.cache.projectSelect;
          tableData.forEach(function (row) {
            if (row.代码 === code) {
              if (type === "result") {
                row.结果 = result;
              }
            }
          });

          table.reload("projectSelect", {
            data: tableData,
          });
        }

        // 加载表格
        loadTable();
      });
    </script>
  </body>
</html>

因为现在layui使用场景已经很少,且上面注释较为详细,此处就不再过多赘述了。

希望本文对您有所帮助!

感谢阅读w

相关推荐
咸鱼翻面儿1 分钟前
Javascript异步,这次我真弄懂了!!!
javascript
brrdg_sefg2 分钟前
Rust 在前端基建中的使用
前端·rust·状态模式
m0_7482309426 分钟前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
qq_5895681034 分钟前
Echarts的高级使用,动画,交互api
前端·javascript·echarts
黑客老陈2 小时前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
运维·服务器·前端·网络·安全·web3·xss
正小安2 小时前
Vite系列课程 | 11. Vite 配置文件中 CSS 配置(Modules 模块化篇)
前端·vite
暴富的Tdy2 小时前
【CryptoJS库AES加密】
前端·javascript·vue.js
neeef_se2 小时前
Vue中使用a标签下载静态资源文件(比如excel、pdf等),纯前端操作
前端·vue.js·excel
m0_748235612 小时前
web 渗透学习指南——初学者防入狱篇
前端