使用jQuery拖动后,在表格中选择单元格

时间:2017-12-13 14:04:30

标签: jquery

我正在尝试构建一种直接的方法来选择表格中的单元格。选择取决于使用鼠标拖动的起点和终点,类似于Excel中的工作方式。

只要您从左向右拖动,从上到下拖动,我的当前解决方案就可以正常工作。我试图通过排序坐标来解决这个问题,但这没有帮助。相反,现在总是在您拖动的方向(水平或垂直)中选择两个单元格。我似乎无法弄明白为什么。

主要思想是:

  • onmousedown:使用行和单元格idnex存储起始单元格的坐标
  • onmouseover / onmouseleave:存储结束单元格的坐标
  • 在每个事件中,将行及其子项切片以获得坐标
  • 给出的正确范围

我觉得我在思考错误,但我不知道哪一个。

function markSelection(selection) {
  // Sort coordinates (start-end point) numerically
  selection["x"] = selection["x"].sort(sortNumbers);
  selection["y"] = selection["y"].sort(sortNumbers);

  // Only get relevant rows within range
  const rows = $("#pixels>tbody tr").slice(selection["y"][0], selection["y"][1] + 1);
  $("#pixels>tbody tr td").removeClass("selected");
  let cells = $();
  // In each relevant row, get the relevant cells
  rows.each(function(i, el) {
    cells = cells.add($(el).children("td").slice(selection["x"][0], selection["x"][1] + 1));
  });
  cells.addClass("selected");
}

function sortNumbers(a, b) {
  return a - b;
}

let isDragging = false;
let selection = {};

$("#pixels").on("mousedown", "td", function() {
  // Start dragging
  isDragging = true;

  const $this = $(this);
  selection["x"] = [$this.index(), $this.index()];
  selection["y"] = [$this.parent("tr").index(), $this.parent("tr").index()];
  markSelection(selection);
}).on("mouseover", "td", function() {
  if (isDragging) {
    const $this = $(this);
    selection["x"][1] = $this.index();
    selection["y"][1] = $this.parent("tr").index();
    markSelection(selection);
  }
}).on("mouseup", "td", function() {
  // End dragging
  isDragging = false;

  const $this = $(this);
  selection["x"][1] = $this.index();
  selection["y"][1] = $this.parent("tr").index();
  markSelection(selection);
}).on("mouseleave", function() {
  // End dragging
  isDragging = false;
});
#pixels {
  border-collapse: collapse;
}

#pixels td {
  border: 1px solid black;
  width: 64px;
  height: 64px;
}

#pixels td.selected {
  outline: 3px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="pixels">
  <tbody style="background-color: rgb(255, 255, 255);">
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
  </tbody>
</table>

1 个答案:

答案 0 :(得分:1)

一种解决方法是在对副本进行排序和排序之前复制坐标数组,并使用复制结果对行和单元格进行切片。

另一个是使用Math.max&amp; Math.min得到开始/结束而不是排序

原始数组的排序是在向上或向左移动时切换起点和终点导致问题的原因

&#13;
&#13;
function markSelection(selection) {
  // make copies before sorting
  const coords = {
    x: selection["x"].slice().sort(sortNumbers),
    y: selection["y"].slice().sort(sortNumbers)
  }
  // Only get relevant rows within range
  const rows = $("#pixels>tbody tr").slice(coords["y"][0], coords["y"][1] + 1);
  $("#pixels>tbody tr td").removeClass("selected");
  let cells = $();
  // In each relevant row, get the relevant cells
  rows.each(function(i, el) {
    cells = cells.add($(el).children("td").slice(coords["x"][0], coords["x"][1] + 1));
  });
  cells.addClass("selected");
}

function sortNumbers(a, b) {
  return a - b;
}

let isDragging = false;
let selection = {};

$("#pixels").on("mousedown", "td", function() {
  // Start dragging
  isDragging = true;

  const $this = $(this);
  selection["x"] = [$this.index(), $this.index()];
  selection["y"] = [$this.parent("tr").index(), $this.parent("tr").index()];
  markSelection(selection);
}).on("mouseover", "td", function() {
  if (isDragging) {
    const $this = $(this);
    selection["x"][1] = $this.index();
    selection["y"][1] = $this.parent("tr").index();
    markSelection(selection);
  }
}).on("mouseup", "td", function() {
  // End dragging
  isDragging = false;

  const $this = $(this);
  selection["x"][1] = $this.index();
  selection["y"][1] = $this.parent("tr").index();
  markSelection(selection);
}).on("mouseleave", function() {
  // End dragging
  isDragging = false;
});
&#13;
#pixels {
  border-collapse: collapse;
}

#pixels td {
  border: 1px solid black;
  width: 64px;
  height: 64px;
}

#pixels td.selected {
  outline: 3px solid red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="pixels">
  <tbody style="background-color: rgb(255, 255, 255);">
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
    <tr>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
      <td style="border-color:#000000;"></td>
    </tr>
  </tbody>
</table>
&#13;
&#13;
&#13;