0

I started re-writing Windows! The code below draws 10 canvas objects you can move around. I made them random sizes. When you click on one it has thicker outline and can be dragged around.

When I added one line to change the initial top position of the canvases the move stopped working. Its very odd, I only wanted to stack the windows in increasing 10px steps rather then them all starting at the same spot. Why could this minor change stop the rest working?

var n = 0,
  canv = [],
  ct = []
var body = document.getElementsByTagName("body")[0];
var targ, wind = 10,
  i, offx, offy = 0
for (n = 0; n < wind; n++) {
  canv[n] = document.createElement('canvas');
  canv[n].id = "C" + n;
  canv[n].width = rnd(30 * n);
  canv[n].height = rnd(30 * n);
  //canv[n].style.top=10*n     <- This line stops the drag effect working
  canv[n].style.zIndex = n;
  canv[n].style.position = "absolute";
  canv[n].style.border = "2px solid";

  body.appendChild(canv[n]);
 targ=canv[0]    // added now to stop errors before first click
  ct[n] = canv[n].getContext("2d");
  ct[n].fillText(n, canv[n].width / 2, canv[n].height / 2)

  canv[n].addEventListener('mousedown', function(e) {
    targ = e.currentTarget
    if (targ.style.border == "2px solid") {
      for (i = 0; i < wind; i++) {
        canv[i].style.border = "2px solid"
      }
      targ.style.border = "5px solid";
      offy = e.y - targ.style.top
    } else {
      targ.style.border = "2px solid"
    }
  });
  canv[n].addEventListener('mousemove', function(e) {
    if (targ.style.border == "5px solid") {
      move(e.x, e.y)
    }
  });
}

function move(x, y) {
  targ.style.top = y - offy
}

function rnd(m) {
  return Math.floor(Math.random() * m)
}
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
EV123
  • 21
  • 6
  • 1
    You really should add and remove a class instead of setting styles and checking styles – epascarello Dec 02 '22 at 17:53
  • targ is not set until you click your mouse so the mousemove throws tons of errors. – epascarello Dec 02 '22 at 17:56
  • ah Epascarello, how do I add a class? – EV123 Dec 02 '22 at 18:04
  • @EV123 Using the [`classList` API](//developer.mozilla.org/en/docs/Web/API/Element/classList), but since everything is calculated, I recommend [using CSS custom properties (variables)](//developer.mozilla.org/en/docs/Web/CSS/Using_CSS_custom_properties) instead. [`top`](//developer.mozilla.org/en/docs/Web/CSS/top) requires a [``](//developer.mozilla.org/en/docs/Web/CSS/length) or a [``](//developer.mozilla.org/en/docs/Web/CSS/percentage). You’re setting it to a [``](//developer.mozilla.org/en/docs/Web/CSS/number) instead. [Make a string](/q/1408289/4642212). – Sebastian Simon Dec 02 '22 at 18:11
  • @Sebastian, ok so I tried canv[n].style.top=n+'%' That didnt work either! – EV123 Dec 02 '22 at 18:14
  • @EV123 That’s not the only place. That’s also not the only mistake. – Sebastian Simon Dec 02 '22 at 18:18

1 Answers1

1

You are using a global variable for when it is active. That is not set until a click happens so you get tons of errors.

When you are setting a position, it needs some sort of units.

Basic idea with the code cleaned up a bit.

const canv = [];
const ct = [];

const body = document.getElementsByTagName("body")[0];

let targ, wind = 10,
  i, offx, offy = 0;

for (let n = 0; n < wind; n++) {
  const canvas = document.createElement('canvas');
  canv[n] = canvas;
  
  canvas.id = "C" + n;

  const width = rnd(30 * n);
  const height = rnd(30 * n);
  
  canvas.style.width = width + "px";
  canvas.style.height = height + "px";
  canvas.style.top = (10 * n) + "px";
  canvas.style.left = (10 * n) + "px";
  canvas.style.zIndex = n;
  
  body.appendChild(canvas);

  const ctx = canvas.getContext("2d");
  ct[n] = ctx;
  ctx.fillText(n, width / 2, height / 2)

  canvas.addEventListener('mousedown', function(e) {
    document.querySelectorAll("canvas.active").forEach(elem => {
      elem.classList.remove("active");
    });
    targ = e.currentTarget;
    targ.classList.add("active");
  });

  canvas.addEventListener('mousemove', function(e) {
    if (targ && targ.classList.contains('active')) {
      move(e.x, e.y)
    }
  });
}

function move(x, y) {
  targ.style.top = y - offy + "px"
}

function rnd(m) {
  return Math.floor(Math.random() * m)
}
canvas {
  position: absolute;
  min-width: 30px;
  min-height: 30px;
  border: 2px solid black;
  z-index: 1;
}

canvas.active {
  border: 5px solid black;
}
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • One thing I dont get, in your code clean up you added const ctx = canvas.getContext("2d"); ct[n] = ctx; I thought const cant be redefined, and its in a loop so const will be set 10 different times, so how can it redifine that const? Whats the advantage to putting it to a const before adding it to the array anyway – EV123 Dec 02 '22 at 18:26
  • 1
    const is redefined in a block. Each iteration of the loop is a new variable. – epascarello Dec 02 '22 at 18:35