'How can I highlight the box as I'm creating it?

Currently the box only appears after you stop dragging. I want to outline the box as its being created.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Billion Satoshis</title>
    <script type="module">
      let cells = Math.pow(256, 2);
      document.addEventListener("DOMContentLoaded", main);

      function main() {
        const view = document.getElementById("scroller");
        const grid = [];

        for (let i = 0; i < cells; i++) {
          const el = document.createElement("div");

          el.classList.add("cell");
          grid.push(el);
        }

        view.append(...grid);

        view.style.gridTemplateColumns = `repeat(${Math.sqrt(cells)}, 10px)`;

        /* added */
        const selectionLayer = document.getElementById("selectionLayer");
        let isMouseDown = false;
        let isMultiSelectionOn = false;
        let selectionStart = {},
          selectionEnd = {};
        let selectionRect = {};
        let scrollBarCorrection_x = view.offsetWidth - view.clientWidth;
        let scrollBarCorrection_y = view.offsetHeight - view.clientHeight;
        let selectionMargin = {
          width: 10,
          height: 5,
        };

        view.addEventListener("mousedown", (e) => {
          isMouseDown = true;

          if (!isMultiSelectionOn) {
            selectionEnd = {
              x: null,
              y: null,
            };
            clearSecelction();
          }

          selectionStart = {
            x: e.x - view.offsetLeft,
            y: e.y - view.offsetTop,
          };
        });

        view.addEventListener("mouseup", (e) => {
          isMouseDown = false;

          selectionEnd = {
            x: e.x - view.offsetLeft,
            y: e.y - view.offsetTop,
          };

          if (
            Math.abs(selectionEnd.x - selectionStart.x) <
              selectionMargin.width ||
            Math.abs(selectionEnd.y - selectionStart.y) < selectionMargin.height
          )
            return;

          selectionLayer.style.top = `0px`;
          selectionLayer.style.left = `0px`;
          selectionLayer.style.bottom = "unset";
          selectionLayer.style.right = "unset";
          selectionLayer.style.visibility = "hidden";

          getSelectedCells().forEach((c) => c.classList.add("selected"));
        });

        view.addEventListener("mousemove", (e) => {
          if (!isMouseDown) return;

          selectionEnd = {
            x: e.x,
            y: e.y,
          };

          selectionRect = {
            x1: Math.min(selectionStart.x, selectionEnd.x),
            y1: Math.min(selectionStart.y, selectionEnd.y),
            x2:
              Math.max(selectionStart.x, selectionEnd.x) +
              scrollBarCorrection_x,
            y2:
              Math.max(selectionStart.y, selectionEnd.y) +
              scrollBarCorrection_y,
          };

          selectionLayer.style.top = `${Math.min(
            selectionRect.y1,
            selectionRect.y2
          )}px`;
          selectionLayer.style.left = `${Math.min(
            selectionRect.x1,
            selectionRect.x2
          )}px`;
          selectionLayer.style.bottom = `${
            view.offsetHeight +
            view.offsetTop -
            Math.max(selectionRect.y1, selectionRect.y2)
          }px`;
          selectionLayer.style.right = `${
            view.offsetWidth +
            view.offsetLeft -
            Math.max(selectionRect.x1, selectionRect.x2)
          }px`;

          selectionLayer.style.visibility = "visible";

          if (!isMultiSelectionOn) clearSecelction();
        });

        function clearSecelction() {
          view
            .querySelectorAll(".cell")
            .forEach((c) => c.classList.remove("selected"));
        }

        function getSelectedCells() {
          let selectedCells = [];
          const cells = view.querySelectorAll(".cell");
          cells.forEach((c) => {
            const bounds = c.getBoundingClientRect();

            selectionLayer.style.visibility = "visible";

            if (
              selectionRect.x1 <= bounds.left - view.offsetLeft &&
              selectionRect.y1 <= bounds.top - view.offsetTop &&
              selectionRect.x2 - scrollBarCorrection_x >=
                bounds.right - view.offsetLeft &&
              selectionRect.y2 - scrollBarCorrection_y >= bounds.bottom
            )
              selectedCells.push(c);
          });
          return selectedCells;
        }

        document.addEventListener("keydown", (e) => {
          if (e.ctrlKey) isMultiSelectionOn = true;
        });
        document.addEventListener("keyup", (e) => {
          if (!e.ctrlKey) isMultiSelectionOn = false;
        });
        document.addEventListener("resize", () => {
          scrollBarCorrection_x = view.offsetWidth - view.clientWidth;
          scrollBarCorrection_y = view.offsetHeight - view.clientHeight;
        });
      }
    </script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      html {
        font-size: 62.5%;
      }

      body {
        font-size: 1.6rem;
        font-family: sans-serif;
      }

      h1 {
        font-size: 2rem;
      }

      #view {
        width: calc(100vw - 2rem);
        height: calc(100vh - 10rem);
        margin: auto;
        background-color: #eee;
        border: 1px solid black;
        overflow: auto;
        display: grid;
        gap: 0;
        border-top: 1px solid black;
        border-left: 1px solid black;
        position: relative;
        user-select: none;
      }

      header {
        text-align: center;
      }

      .cell {
        width: 1rem;
        height: 1rem;
        border-right: 1px solid black;
        border-bottom: 1px solid black;
      }

      .cell.selected {
        background-color: #5eba7d;
      }

      #scroller {
        position: absolute;
        height: 100%;
        width: 100%;
        display: grid;
        grid-template-columns: repeat(640, 10px);
        gap: 0;
      }

      #selectionLayer {
        position: absolute;
        top: 0px;
        left: 0px;
        border: 1px solid #5eba7d;
        background-color: #5eba7d45;
        z-index: 99999;
      }
    </style>
  </head>

  <body>
    <header>
      <h1>Billion Satoshis</h1>
      <p>Pixel based advertising for crypto</p>
      <p><small>$1/square (svg only)</small></p>
    </header>
    <section id="view">
      <div id="scroller">
        <div id="selectionLayer"></div>
      </div>
    </section>
  </body>
</html>

JSFiddel: https://jsfiddle.net/chovy/cs36ykrm/



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source