原生表格的拖拽选中,并添加外边框颜色

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device - width, initial - scale = 1.0">
  <style>
    table {
      border-collapse: collapse;
      cursor: pointer;
    }

    table td {
      border: 1px solid black;
      padding: 5px;
    }

    .selected {
      background-color: lightblue;
    }

    .selected-group {
      border-top: 2px solid green !important;
      border-bottom: 2px solid green !important;
      border-left: 2px solid green !important;
      border-right: 2px solid green !important;
    }

    .selected-group1 {
      border-top: 2px solid green !important;
    }

    .selected-group2 {
      border-bottom: 2px solid green !important;
    }

    .selected-group3 {
      border-left: 2px solid green !important;
    }

    .selected-group4 {
      border-right: 2px solid green !important;
    }

    ::selection {
      background-color: transparent;
    }
  </style>
</head>

<body>
  <span onclick="redata()">1111</span>
  <button onclick="createTable()">创建表格</button>
  <div id="table-container"></div>

  <script>
    // 开始单元格
    let startCell;
    // 是否在拖拽中
    let isDragging = false;
    // 选中的单元格
    let selectedCells = [];

    function createTable () {
      const table = document.createElement('table');
      table.id = 'myTable';
      for (let i = 0; i < 5; i++) {
        const row = document.createElement('tr');
        for (let j = 0; j < 5; j++) {
          const cell = document.createElement('td');
          cell.textContent = `Cell ${i * 5 + j + 1}`;
          // 为每个单元格添加监听事件
          cell.addEventListener('mousedown', function (e) {
            startCell = this;
            isDragging = true;
            selectCell(this);
          });
          // 鼠标划过事件
          cell.addEventListener('mouseover', function () {
            if (isDragging) {
              console.log('4');
              selectCell(this);
            }
          });
          // 鼠标抬起时清空
          cell.addEventListener('mouseup', function () {
            isDragging = false;
          });
          // 鼠标点击时事件
          cell.addEventListener('click', function () {
            if (!isDragging) {
              toggleCellSelection(this);
            }
          });
          row.appendChild(cell);
        }
        table.appendChild(row);
      }
      const tableContainer = document.getElementById('table-container');
      tableContainer.innerHTML = '';
      tableContainer.appendChild(table);
    }
    // 鼠标放下
    function selectCell (cell) {
      // 清空之前的选项
      clearSelection();
      // 初始点击的单元格的行与列
      const startRowIndex = startCell.parentNode.rowIndex;
      const startCellIndex = Array.from(startCell.parentNode.cells).indexOf(startCell);
      // console.log('行:',startRowIndex,'列:',startCellIndex);
      // 当前划过的行与列
      const endRowIndex = cell.parentNode.rowIndex;
      const endCellIndex = Array.from(cell.parentNode.cells).indexOf(cell);
      // console.log('行:',endRowIndex,'列:',endCellIndex);
      // 正着选倒着选都行
      for (let row = Math.min(startRowIndex, endRowIndex); row <= Math.max(startRowIndex, endRowIndex); row++) {
        // 获取table表格中相应行数据内全部单元格数组
        const rowCells = document.getElementById('myTable').rows[row].cells;
        for (let col = Math.min(startCellIndex, endCellIndex); col <= Math.max(startCellIndex, endCellIndex); col++) {
          rowCells[col].classList.add('selected');
          selectedCells.push(rowCells[col]);
        }
      }
      updateGroupBorder();
    }

    function toggleCellSelection (cell) {
      if (cell.classList.contains('selected')) {
        cell.classList.remove('selected');
        selectedCells = selectedCells.filter(c => c !== cell);
      } else {
        cell.classList.add('selected');
        selectedCells.push(cell);
      }
      updateGroupBorder();
    }
    // 鼠标放下首现清空选择
    function clearSelection () {
      const allSelected = document.getElementsByClassName('selected');
      console.log(allSelected.length, 'allSelected.length');
      while (allSelected.length > 0) {
        allSelected[0].classList.remove('selected');
      }
      selectedCells = [];
      removeGroupBorder();
    }

    function updateGroupBorder () {
      removeGroupBorder();
      if (selectedCells.length > 0) {
        const minRowIndex = Math.min.apply(null, Array.from(selectedCells).map(cell => cell.parentNode.rowIndex));
        const maxRowIndex = Math.max.apply(null, Array.from(selectedCells).map(cell => cell.parentNode.rowIndex));
        const minCellIndex = Math.min.apply(null, Array.from(selectedCells).map(cell => Array.from(cell.parentNode.cells).indexOf(cell)));
        const maxCellIndex = Math.max.apply(null, Array.from(selectedCells).map(cell => Array.from(cell.parentNode.cells).indexOf(cell)));
        const table = document.getElementById('myTable');
        // 顶部边框
        for (let col = minCellIndex; col <= maxCellIndex; col++) {
          table.rows[minRowIndex].cells[col].classList.add('selected-group1');
        }
        // 底部边框
        for (let col = minCellIndex; col <= maxCellIndex; col++) {
          table.rows[maxRowIndex].cells[col].classList.add('selected-group2');
        }
        // 左边框
        for (let row = minRowIndex; row <= maxRowIndex; row++) {
          table.rows[row].cells[minCellIndex].classList.add('selected-group3');
        }
        // 右边框
        for (let row = minRowIndex; row <= maxRowIndex; row++) {
          table.rows[row].cells[maxCellIndex].classList.add('selected-group4');
        }
      }
    }
    // 清除外边框
    function removeGroupBorder () {
      const allGroupBordered1 = document.getElementsByClassName('selected-group1');
      while (allGroupBordered1.length > 0) {
        allGroupBordered1[0].classList.remove('selected-group1');
      }
      const allGroupBordered2 = document.getElementsByClassName('selected-group2');
      while (allGroupBordered2.length > 0) {
        allGroupBordered2[0].classList.remove('selected-group2');
      }
      const allGroupBordered3 = document.getElementsByClassName('selected-group3');
      while (allGroupBordered3.length > 0) {
        allGroupBordered3[0].classList.remove('selected-group3');
      }
      const allGroupBordered4 = document.getElementsByClassName('selected-group4');
      while (allGroupBordered4.length > 0) {
        allGroupBordered4[0].classList.remove('selected-group4');
      }
    }
    function redata () {
      let sumNumbers = 0;
      let i = 1;
      while (i <= 10) {
        sumNumbers += i;
        i++;
        console.log(i);
      }
    }
  </script>
</body>

</html>

主要是通过事件的监听来实现选中初始的行和列的定位,和终点的行和列的定位,然后根据四个点找到所在区域内的所有cell,找到之后判断位置,分别加上上,下,左,右四种边框。这是主要实现的思路,

然后还涉及到的就是清空操作,一般就是每移动一次都要进行大量的操作,所以只是能实现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值