title: Select cells within range in table after dragging with jQuery
body: <p>I am trying to build a straightforward way to select cells in a table. Selecting is determined by the start and end point of dragging with a mouse, similar to how it works in Excel.</p>
  
  <p>My current solution works as long as you drag from left to right and top to bottom. I tried to counter this by sorting the coordinates but that did not help. Instead, now always two cells are selected in the direction you are dragging in (horizontal or vertical). I can't seem to figure out why.</p>
  
  <p>The main idea is:</p>
  
  <ul>
  <li>onmousedown: store starting cell's coordinates by using row and cell idnex</li>
  <li>onmouseover/onmouseleave: store ending cell's coordinates</li>
  <li>On every event, slice down the rows and their children to get the correct range as given by the coordinates</li>
  </ul>
  
  <p>I feel like I am making a thinking error but I do'nt see which one.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>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&gt;tbody tr").slice(selection["y"][0], selection["y"][1] + 1);
    $("#pixels&gt;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;
  });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>#pixels {
    border-collapse: collapse;
  }
  
  #pixels td {
    border: 1px solid black;
    width: 64px;
    height: 64px;
  }
  
  #pixels td.selected {
    outline: 3px solid red;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;table id="pixels"&gt;
    &lt;tbody style="background-color: rgb(255, 255, 255);"&gt;
      &lt;tr&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
        &lt;td style="border-color:#000000;"&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;</code></pre>
  </div>
  </div>
  </p>